diff options
Diffstat (limited to 'drivers/media')
336 files changed, 11364 insertions, 3741 deletions
diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index f8a808d45034..98f88c43f62c 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -86,7 +86,7 @@ void cec_queue_event_fh(struct cec_fh *fh, const struct cec_event *new_ev, u64 ts) { static const u8 max_events[CEC_NUM_EVENTS] = { - 1, 1, 64, 64, + 1, 1, 64, 64, 8, 8, }; struct cec_event_entry *entry; unsigned int ev_idx = new_ev->event - 1; @@ -170,6 +170,22 @@ void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high, ktime_t ts) } EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event); +/* Notify userspace that the HPD pin changed state at the given time. */ +void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts) +{ + struct cec_event ev = { + .event = is_high ? CEC_EVENT_PIN_HPD_HIGH : + CEC_EVENT_PIN_HPD_LOW, + }; + struct cec_fh *fh; + + mutex_lock(&adap->devnode.lock); + list_for_each_entry(fh, &adap->devnode.fhs, list) + cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); + mutex_unlock(&adap->devnode.lock); +} +EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event); + /* * Queue a new message for this filehandle. * diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c index a079f7fe018c..3dba3aa34a43 100644 --- a/drivers/media/cec/cec-api.c +++ b/drivers/media/cec/cec-api.c @@ -32,6 +32,7 @@ #include <media/cec-pin.h> #include "cec-priv.h" +#include "cec-pin-priv.h" static inline struct cec_devnode *cec_devnode_data(struct file *filp) { @@ -529,7 +530,7 @@ static int cec_open(struct inode *inode, struct file *filp) * Initial events that are automatically sent when the cec device is * opened. */ - struct cec_event ev_state = { + struct cec_event ev = { .event = CEC_EVENT_STATE_CHANGE, .flags = CEC_EVENT_FL_INITIAL_STATE, }; @@ -569,9 +570,19 @@ static int cec_open(struct inode *inode, struct file *filp) filp->private_data = fh; /* Queue up initial state events */ - ev_state.state_change.phys_addr = adap->phys_addr; - ev_state.state_change.log_addr_mask = adap->log_addrs.log_addr_mask; - cec_queue_event_fh(fh, &ev_state, 0); + ev.state_change.phys_addr = adap->phys_addr; + ev.state_change.log_addr_mask = adap->log_addrs.log_addr_mask; + cec_queue_event_fh(fh, &ev, 0); +#ifdef CONFIG_CEC_PIN + if (adap->pin && adap->pin->ops->read_hpd) { + err = adap->pin->ops->read_hpd(adap); + if (err >= 0) { + ev.event = err ? CEC_EVENT_PIN_HPD_HIGH : + CEC_EVENT_PIN_HPD_LOW; + cec_queue_event_fh(fh, &ev, 0); + } + } +#endif list_add(&fh->list, &devnode->fhs); mutex_unlock(&devnode->lock); diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index 648136e552d5..5870da6a567f 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -112,10 +112,6 @@ static int __must_check cec_devnode_register(struct cec_devnode *devnode, int minor; int ret; - /* Initialization */ - INIT_LIST_HEAD(&devnode->fhs); - mutex_init(&devnode->lock); - /* Part 1: Find a free minor number */ mutex_lock(&cec_devnode_lock); minor = find_next_zero_bit(cec_devnode_nums, CEC_NUM_DEVICES, 0); @@ -242,6 +238,10 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, INIT_LIST_HEAD(&adap->wait_queue); init_waitqueue_head(&adap->kthread_waitq); + /* adap->devnode initialization */ + INIT_LIST_HEAD(&adap->devnode.fhs); + mutex_init(&adap->devnode.lock); + adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name); if (IS_ERR(adap->kthread)) { pr_err("cec-%s: kernel_thread() failed\n", name); @@ -277,7 +277,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, adap->rc->input_id.version = 1; adap->rc->driver_name = CEC_NAME; adap->rc->allowed_protocols = RC_PROTO_BIT_CEC; - adap->rc->enabled_protocols = RC_PROTO_BIT_CEC; adap->rc->priv = adap; adap->rc->map_name = RC_MAP_CEC; adap->rc->timeout = MS_TO_NS(100); diff --git a/drivers/media/cec/cec-pin-priv.h b/drivers/media/cec/cec-pin-priv.h new file mode 100644 index 000000000000..7d0def199762 --- /dev/null +++ b/drivers/media/cec/cec-pin-priv.h @@ -0,0 +1,133 @@ +/* + * cec-pin-priv.h - internal cec-pin header + * + * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef LINUX_CEC_PIN_PRIV_H +#define LINUX_CEC_PIN_PRIV_H + +#include <linux/types.h> +#include <linux/atomic.h> +#include <media/cec-pin.h> + +enum cec_pin_state { + /* CEC is off */ + CEC_ST_OFF, + /* CEC is idle, waiting for Rx or Tx */ + CEC_ST_IDLE, + + /* Tx states */ + + /* Pending Tx, waiting for Signal Free Time to expire */ + CEC_ST_TX_WAIT, + /* Low-drive was detected, wait for bus to go high */ + CEC_ST_TX_WAIT_FOR_HIGH, + /* Drive CEC low for the start bit */ + CEC_ST_TX_START_BIT_LOW, + /* Drive CEC high for the start bit */ + CEC_ST_TX_START_BIT_HIGH, + /* Drive CEC low for the 0 bit */ + CEC_ST_TX_DATA_BIT_0_LOW, + /* Drive CEC high for the 0 bit */ + CEC_ST_TX_DATA_BIT_0_HIGH, + /* Drive CEC low for the 1 bit */ + CEC_ST_TX_DATA_BIT_1_LOW, + /* Drive CEC high for the 1 bit */ + CEC_ST_TX_DATA_BIT_1_HIGH, + /* + * Wait for start of sample time to check for Ack bit or first + * four initiator bits to check for Arbitration Lost. + */ + CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE, + /* Wait for end of bit period after sampling */ + CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE, + + /* Rx states */ + + /* Start bit low detected */ + CEC_ST_RX_START_BIT_LOW, + /* Start bit high detected */ + CEC_ST_RX_START_BIT_HIGH, + /* Wait for bit sample time */ + CEC_ST_RX_DATA_SAMPLE, + /* Wait for earliest end of bit period after sampling */ + CEC_ST_RX_DATA_POST_SAMPLE, + /* Wait for CEC to go high (i.e. end of bit period */ + CEC_ST_RX_DATA_HIGH, + /* Drive CEC low to send 0 Ack bit */ + CEC_ST_RX_ACK_LOW, + /* End of 0 Ack time, wait for earliest end of bit period */ + CEC_ST_RX_ACK_LOW_POST, + /* Wait for CEC to go high (i.e. end of bit period */ + CEC_ST_RX_ACK_HIGH_POST, + /* Wait for earliest end of bit period and end of message */ + CEC_ST_RX_ACK_FINISH, + + /* Start low drive */ + CEC_ST_LOW_DRIVE, + /* Monitor pin using interrupts */ + CEC_ST_RX_IRQ, + + /* Total number of pin states */ + CEC_PIN_STATES +}; + +#define CEC_NUM_PIN_EVENTS 128 + +#define CEC_PIN_IRQ_UNCHANGED 0 +#define CEC_PIN_IRQ_DISABLE 1 +#define CEC_PIN_IRQ_ENABLE 2 + +struct cec_pin { + struct cec_adapter *adap; + const struct cec_pin_ops *ops; + struct task_struct *kthread; + wait_queue_head_t kthread_waitq; + struct hrtimer timer; + ktime_t ts; + unsigned int wait_usecs; + u16 la_mask; + bool enabled; + bool monitor_all; + bool rx_eom; + bool enable_irq_failed; + enum cec_pin_state state; + struct cec_msg tx_msg; + u32 tx_bit; + bool tx_nacked; + u32 tx_signal_free_time; + struct cec_msg rx_msg; + u32 rx_bit; + + struct cec_msg work_rx_msg; + u8 work_tx_status; + ktime_t work_tx_ts; + atomic_t work_irq_change; + atomic_t work_pin_events; + unsigned int work_pin_events_wr; + unsigned int work_pin_events_rd; + ktime_t work_pin_ts[CEC_NUM_PIN_EVENTS]; + bool work_pin_is_high[CEC_NUM_PIN_EVENTS]; + ktime_t timer_ts; + u32 timer_cnt; + u32 timer_100ms_overruns; + u32 timer_300ms_overruns; + u32 timer_max_overrun; + u32 timer_sum_overrun; +}; + +#endif diff --git a/drivers/media/cec/cec-pin.c b/drivers/media/cec/cec-pin.c index c003b8eac617..b48dfe844118 100644 --- a/drivers/media/cec/cec-pin.c +++ b/drivers/media/cec/cec-pin.c @@ -20,6 +20,7 @@ #include <linux/sched/types.h> #include <media/cec-pin.h> +#include "cec-pin-priv.h" /* All timings are in microseconds */ @@ -132,7 +133,7 @@ static void cec_pin_to_idle(struct cec_pin *pin) pin->rx_msg.len = 0; memset(pin->rx_msg.msg, 0, sizeof(pin->rx_msg.msg)); pin->state = CEC_ST_IDLE; - pin->ts = 0; + pin->ts = ns_to_ktime(0); } /* @@ -426,7 +427,7 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts) v = cec_pin_read(pin); if (v && pin->rx_eom) { pin->work_rx_msg = pin->rx_msg; - pin->work_rx_msg.rx_ts = ts; + pin->work_rx_msg.rx_ts = ktime_to_ns(ts); wake_up_interruptible(&pin->kthread_waitq); pin->ts = ts; pin->state = CEC_ST_RX_ACK_FINISH; @@ -457,7 +458,7 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) s32 delta; ts = ktime_get(); - if (pin->timer_ts) { + if (ktime_to_ns(pin->timer_ts)) { delta = ktime_us_delta(ts, pin->timer_ts); pin->timer_cnt++; if (delta > 100 && pin->state != CEC_ST_IDLE) { @@ -481,17 +482,19 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) if (pin->wait_usecs > 150) { pin->wait_usecs -= 100; pin->timer_ts = ktime_add_us(ts, 100); - hrtimer_forward_now(timer, 100000); + hrtimer_forward_now(timer, ns_to_ktime(100000)); return HRTIMER_RESTART; } if (pin->wait_usecs > 100) { pin->wait_usecs /= 2; pin->timer_ts = ktime_add_us(ts, pin->wait_usecs); - hrtimer_forward_now(timer, pin->wait_usecs * 1000); + hrtimer_forward_now(timer, + ns_to_ktime(pin->wait_usecs * 1000)); return HRTIMER_RESTART; } pin->timer_ts = ktime_add_us(ts, pin->wait_usecs); - hrtimer_forward_now(timer, pin->wait_usecs * 1000); + hrtimer_forward_now(timer, + ns_to_ktime(pin->wait_usecs * 1000)); pin->wait_usecs = 0; return HRTIMER_RESTART; } @@ -531,7 +534,7 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) pin->state = CEC_ST_RX_START_BIT_LOW; break; } - if (pin->ts == 0) + if (ktime_to_ns(pin->ts) == 0) pin->ts = ts; if (pin->tx_msg.len) { /* @@ -572,12 +575,13 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) if (!adap->monitor_pin_cnt || states[pin->state].usecs <= 150) { pin->wait_usecs = 0; pin->timer_ts = ktime_add_us(ts, states[pin->state].usecs); - hrtimer_forward_now(timer, states[pin->state].usecs * 1000); + hrtimer_forward_now(timer, + ns_to_ktime(states[pin->state].usecs * 1000)); return HRTIMER_RESTART; } pin->wait_usecs = states[pin->state].usecs - 100; pin->timer_ts = ktime_add_us(ts, 100); - hrtimer_forward_now(timer, 100000); + hrtimer_forward_now(timer, ns_to_ktime(100000)); return HRTIMER_RESTART; } @@ -596,7 +600,7 @@ static int cec_pin_thread_func(void *_adap) if (pin->work_rx_msg.len) { cec_received_msg_ts(adap, &pin->work_rx_msg, - pin->work_rx_msg.rx_ts); + ns_to_ktime(pin->work_rx_msg.rx_ts)); pin->work_rx_msg.len = 0; } if (pin->work_tx_status) { @@ -623,13 +627,15 @@ static int cec_pin_thread_func(void *_adap) pin->ops->disable_irq(adap); cec_pin_high(pin); cec_pin_to_idle(pin); - hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL); + hrtimer_start(&pin->timer, ns_to_ktime(0), + HRTIMER_MODE_REL); break; case CEC_PIN_IRQ_ENABLE: pin->enable_irq_failed = !pin->ops->enable_irq(adap); if (pin->enable_irq_failed) { cec_pin_to_idle(pin); - hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL); + hrtimer_start(&pin->timer, ns_to_ktime(0), + HRTIMER_MODE_REL); } break; default: @@ -653,7 +659,7 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable) cec_pin_read(pin); cec_pin_to_idle(pin); pin->tx_msg.len = 0; - pin->timer_ts = 0; + pin->timer_ts = ns_to_ktime(0); atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED); pin->kthread = kthread_run(cec_pin_thread_func, adap, "cec-pin"); @@ -661,7 +667,8 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable) pr_err("cec-pin: kernel_thread() failed\n"); return PTR_ERR(pin->kthread); } - hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL); + hrtimer_start(&pin->timer, ns_to_ktime(0), + HRTIMER_MODE_REL); } else { if (pin->ops->disable_irq) pin->ops->disable_irq(adap); @@ -699,7 +706,8 @@ static int cec_pin_adap_transmit(struct cec_adapter *adap, u8 attempts, pin->ops->disable_irq(adap); cec_pin_high(pin); cec_pin_to_idle(pin); - hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL); + hrtimer_start(&pin->timer, ns_to_ktime(0), + HRTIMER_MODE_REL); } return 0; } @@ -789,7 +797,7 @@ struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops, caps | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN, CEC_MAX_LOG_ADDRS); - if (PTR_ERR_OR_ZERO(adap)) { + if (IS_ERR(adap)) { kfree(pin); return adap; } diff --git a/drivers/media/common/cypress_firmware.c b/drivers/media/common/cypress_firmware.c index 50e3f76d4847..8895158c1962 100644 --- a/drivers/media/common/cypress_firmware.c +++ b/drivers/media/common/cypress_firmware.c @@ -74,11 +74,9 @@ int cypress_load_firmware(struct usb_device *udev, struct hexline *hx; int ret, pos = 0; - hx = kmalloc(sizeof(struct hexline), GFP_KERNEL); - if (!hx) { - dev_err(&udev->dev, "%s: kmalloc() failed\n", KBUILD_MODNAME); + hx = kmalloc(sizeof(*hx), GFP_KERNEL); + if (!hx) return -ENOMEM; - } /* stop the CPU */ hx->data[0] = 1; diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c index 930d2c94d5d3..8c87d6837c49 100644 --- a/drivers/media/common/saa7146/saa7146_fops.c +++ b/drivers/media/common/saa7146/saa7146_fops.c @@ -163,9 +163,9 @@ void saa7146_buffer_next(struct saa7146_dev *dev, } } -void saa7146_buffer_timeout(unsigned long data) +void saa7146_buffer_timeout(struct timer_list *t) { - struct saa7146_dmaqueue *q = (struct saa7146_dmaqueue*)data; + struct saa7146_dmaqueue *q = from_timer(q, t, timeout); struct saa7146_dev *dev = q->dev; unsigned long flags; @@ -559,7 +559,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) vbi->start[1] = 312; vbi->count[1] = 16; - init_timer(&vv->vbi_read_timeout); + timer_setup(&vv->vbi_read_timeout, NULL, 0); vv->ov_fb.capability = V4L2_FBUF_CAP_LIST_CLIPPING; vv->ov_fb.flags = V4L2_FBUF_FLAG_PRIMARY; diff --git a/drivers/media/common/saa7146/saa7146_vbi.c b/drivers/media/common/saa7146/saa7146_vbi.c index 371c6f8606de..e1d369b976ed 100644 --- a/drivers/media/common/saa7146/saa7146_vbi.c +++ b/drivers/media/common/saa7146/saa7146_vbi.c @@ -349,9 +349,10 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file) spin_unlock_irqrestore(&dev->slock, flags); } -static void vbi_read_timeout(unsigned long data) +static void vbi_read_timeout(struct timer_list *t) { - struct file *file = (struct file*)data; + struct saa7146_vv *vv = from_timer(vv, t, vbi_read_timeout); + struct file *file = vv->vbi_read_timeout_file; struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -366,8 +367,7 @@ static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv) INIT_LIST_HEAD(&vv->vbi_dmaq.queue); - setup_timer(&vv->vbi_dmaq.timeout, saa7146_buffer_timeout, - (unsigned long)(&vv->vbi_dmaq)); + timer_setup(&vv->vbi_dmaq.timeout, saa7146_buffer_timeout, 0); vv->vbi_dmaq.dev = dev; init_waitqueue_head(&vv->vbi_wq); @@ -403,7 +403,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) file, &dev->v4l2_lock); vv->vbi_read_timeout.function = vbi_read_timeout; - vv->vbi_read_timeout.data = (unsigned long)file; + vv->vbi_read_timeout_file = file; /* initialize the brs */ if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) { @@ -489,7 +489,7 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff return ret; } -struct saa7146_use_ops saa7146_vbi_uops = { +const struct saa7146_use_ops saa7146_vbi_uops = { .init = vbi_init, .open = vbi_open, .release = vbi_close, diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c index 37b4654dc21c..2b631eaa65b3 100644 --- a/drivers/media/common/saa7146/saa7146_video.c +++ b/drivers/media/common/saa7146/saa7146_video.c @@ -1201,8 +1201,7 @@ static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv) { INIT_LIST_HEAD(&vv->video_dmaq.queue); - setup_timer(&vv->video_dmaq.timeout, saa7146_buffer_timeout, - (unsigned long)(&vv->video_dmaq)); + timer_setup(&vv->video_dmaq.timeout, saa7146_buffer_timeout, 0); vv->video_dmaq.dev = dev; /* set some default values */ @@ -1303,7 +1302,7 @@ out: return ret; } -struct saa7146_use_ops saa7146_video_uops = { +const struct saa7146_use_ops saa7146_video_uops = { .init = video_init, .open = video_open, .release = video_close, diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index e7a0d7798d5b..c5c827e11b64 100644 --- a/drivers/media/common/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c @@ -447,7 +447,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath) return entry; } } - entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL); + entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (entry) { entry->mode = default_mode; strcpy(entry->devpath, devpath); @@ -521,13 +521,13 @@ static void list_add_locked(struct list_head *new, struct list_head *head, spin_unlock_irqrestore(lock, flags); } -/** +/* * register a client callback that called when device plugged in/unplugged * NOTE: if devices exist callback is called immediately for each device * * @param hotplug callback * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ int smscore_register_hotplug(hotplug_t hotplug) { @@ -536,9 +536,7 @@ int smscore_register_hotplug(hotplug_t hotplug) int rc = 0; kmutex_lock(&g_smscore_deviceslock); - - notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t), - GFP_KERNEL); + notifyee = kmalloc(sizeof(*notifyee), GFP_KERNEL); if (notifyee) { /* now notify callback about existing devices */ first = &g_smscore_devices; @@ -564,7 +562,7 @@ int smscore_register_hotplug(hotplug_t hotplug) } EXPORT_SYMBOL_GPL(smscore_register_hotplug); -/** +/* * unregister a client callback that called when device plugged in/unplugged * * @param hotplug callback @@ -627,7 +625,7 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer, { struct smscore_buffer_t *cb; - cb = kzalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL); + cb = kzalloc(sizeof(*cb), GFP_KERNEL); if (!cb) return NULL; @@ -638,7 +636,7 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer, return cb; } -/** +/* * creates coredev object for a device, prepares buffers, * creates buffer mappings, notifies registered hotplugs about new device. * @@ -646,7 +644,7 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer, * and handlers * @param coredev pointer to a value that receives created coredev object * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ int smscore_register_device(struct smsdevice_params_t *params, struct smscore_device_t **coredev, @@ -655,7 +653,7 @@ int smscore_register_device(struct smsdevice_params_t *params, struct smscore_device_t *dev; u8 *buffer; - dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; @@ -751,7 +749,7 @@ static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, void *buffer, size_t size, struct completion *completion) { int rc; - if (completion == NULL) + if (!completion) return -EINVAL; init_completion(completion); @@ -766,10 +764,10 @@ static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, 0 : -ETIME; } -/** +/* * Starts & enables IR operations * - * @return 0 on success, < 0 on error. + * return: 0 on success, < 0 on error. */ static int smscore_init_ir(struct smscore_device_t *coredev) { @@ -814,13 +812,13 @@ static int smscore_init_ir(struct smscore_device_t *coredev) return 0; } -/** +/* * configures device features according to board configuration structure. * * @param coredev pointer to a coredev object returned by * smscore_register_device * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ static int smscore_configure_board(struct smscore_device_t *coredev) { @@ -863,13 +861,13 @@ static int smscore_configure_board(struct smscore_device_t *coredev) return 0; } -/** +/* * sets initial device mode and notifies client hotplugs that device is ready * * @param coredev pointer to a coredev object returned by * smscore_register_device * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ int smscore_start_device(struct smscore_device_t *coredev) { @@ -1089,7 +1087,7 @@ static char *smscore_fw_lkup[][DEVICE_MODE_MAX] = { }, }; -/** +/* * get firmware file name from one of the two mechanisms : sms_boards or * smscore_fw_lkup. * @param coredev pointer to a coredev object returned by @@ -1098,7 +1096,7 @@ static char *smscore_fw_lkup[][DEVICE_MODE_MAX] = { * @param lookup if 1, always get the fw filename from smscore_fw_lkup * table. if 0, try first to get from sms_boards * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ static char *smscore_get_fw_filename(struct smscore_device_t *coredev, int mode) @@ -1127,7 +1125,7 @@ static char *smscore_get_fw_filename(struct smscore_device_t *coredev, return fw[mode]; } -/** +/* * loads specified firmware into a buffer and calls device loadfirmware_handler * * @param coredev pointer to a coredev object returned by @@ -1135,7 +1133,7 @@ static char *smscore_get_fw_filename(struct smscore_device_t *coredev, * @param filename null-terminated string specifies firmware file name * @param loadfirmware_handler device handler that loads firmware * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, int mode, @@ -1153,8 +1151,8 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, } pr_debug("Firmware name: %s\n", fw_filename); - if (loadfirmware_handler == NULL && !(coredev->device_flags - & SMS_DEVICE_FAMILY2)) + if (!loadfirmware_handler && + !(coredev->device_flags & SMS_DEVICE_FAMILY2)) return -EINVAL; rc = request_firmware(&fw, fw_filename, coredev->device); @@ -1184,14 +1182,14 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, return rc; } -/** +/* * notifies all clients registered with the device, notifies hotplugs, * frees all buffers and coredev object * * @param coredev pointer to a coredev object returned by * smscore_register_device * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ void smscore_unregister_device(struct smscore_device_t *coredev) { @@ -1284,14 +1282,14 @@ static int smscore_detect_mode(struct smscore_device_t *coredev) return rc; } -/** +/* * send init device request and wait for response * * @param coredev pointer to a coredev object returned by * smscore_register_device * @param mode requested mode of operation * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ static int smscore_init_device(struct smscore_device_t *coredev, int mode) { @@ -1301,10 +1299,8 @@ static int smscore_init_device(struct smscore_device_t *coredev, int mode) buffer = kmalloc(sizeof(struct sms_msg_data) + SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA); - if (!buffer) { - pr_err("Could not allocate buffer for init device message.\n"); + if (!buffer) return -ENOMEM; - } msg = (struct sms_msg_data *)SMS_ALIGN_ADDRESS(buffer); SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ, @@ -1319,7 +1315,7 @@ static int smscore_init_device(struct smscore_device_t *coredev, int mode) return rc; } -/** +/* * calls device handler to change mode of operation * NOTE: stellar/usb may disconnect when changing mode * @@ -1327,7 +1323,7 @@ static int smscore_init_device(struct smscore_device_t *coredev, int mode) * smscore_register_device * @param mode requested mode of operation * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) { @@ -1415,13 +1411,13 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) return rc; } -/** +/* * calls device handler to get current mode of operation * * @param coredev pointer to a coredev object returned by * smscore_register_device * - * @return current mode + * return: current mode */ int smscore_get_device_mode(struct smscore_device_t *coredev) { @@ -1429,7 +1425,7 @@ int smscore_get_device_mode(struct smscore_device_t *coredev) } EXPORT_SYMBOL_GPL(smscore_get_device_mode); -/** +/* * find client by response id & type within the clients list. * return client handle or NULL. * @@ -1466,7 +1462,7 @@ found: return client; } -/** +/* * find client by response id/type, call clients onresponse handler * return buffer to pool on error * @@ -1619,13 +1615,13 @@ void smscore_onresponse(struct smscore_device_t *coredev, } EXPORT_SYMBOL_GPL(smscore_onresponse); -/** +/* * return pointer to next free buffer descriptor from core pool * * @param coredev pointer to a coredev object returned by * smscore_register_device * - * @return pointer to descriptor on success, NULL on error. + * return: pointer to descriptor on success, NULL on error. */ static struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev) @@ -1652,7 +1648,7 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) } EXPORT_SYMBOL_GPL(smscore_getbuffer); -/** +/* * return buffer descriptor to a pool * * @param coredev pointer to a coredev object returned by @@ -1686,11 +1682,10 @@ static int smscore_validate_client(struct smscore_device_t *coredev, pr_err("The msg ID already registered to another client.\n"); return -EEXIST; } - listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL); - if (!listentry) { - pr_err("Can't allocate memory for client id.\n"); + listentry = kzalloc(sizeof(*listentry), GFP_KERNEL); + if (!listentry) return -ENOMEM; - } + listentry->id = id; listentry->data_type = data_type; list_add_locked(&listentry->entry, &client->idlist, @@ -1698,7 +1693,7 @@ static int smscore_validate_client(struct smscore_device_t *coredev, return 0; } -/** +/* * creates smsclient object, check that id is taken by another client * * @param coredev pointer to a coredev object from clients hotplug @@ -1710,7 +1705,7 @@ static int smscore_validate_client(struct smscore_device_t *coredev, * @param context client-specific context * @param client pointer to a value that receives created smsclient object * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ int smscore_register_client(struct smscore_device_t *coredev, struct smsclient_params_t *params, @@ -1724,11 +1719,9 @@ int smscore_register_client(struct smscore_device_t *coredev, return -EEXIST; } - newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL); - if (!newclient) { - pr_err("Failed to allocate memory for client.\n"); + newclient = kzalloc(sizeof(*newclient), GFP_KERNEL); + if (!newclient) return -ENOMEM; - } INIT_LIST_HEAD(&newclient->idlist); newclient->coredev = coredev; @@ -1747,7 +1740,7 @@ int smscore_register_client(struct smscore_device_t *coredev, } EXPORT_SYMBOL_GPL(smscore_register_client); -/** +/* * frees smsclient object and all subclients associated with it * * @param client pointer to smsclient object returned by @@ -1778,7 +1771,7 @@ void smscore_unregister_client(struct smscore_client_t *client) } EXPORT_SYMBOL_GPL(smscore_unregister_client); -/** +/* * verifies that source id is not taken by another client, * calls device handler to send requests to the device * @@ -1787,7 +1780,7 @@ EXPORT_SYMBOL_GPL(smscore_unregister_client); * @param buffer pointer to a request buffer * @param size size (in bytes) of request buffer * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ int smsclient_sendrequest(struct smscore_client_t *client, void *buffer, size_t size) @@ -1796,7 +1789,7 @@ int smsclient_sendrequest(struct smscore_client_t *client, struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer; int rc; - if (client == NULL) { + if (!client) { pr_err("Got NULL client\n"); return -EINVAL; } @@ -1804,7 +1797,7 @@ int smsclient_sendrequest(struct smscore_client_t *client, coredev = client->coredev; /* check that no other channel with same id exists */ - if (coredev == NULL) { + if (!coredev) { pr_err("Got NULL coredev\n"); return -EINVAL; } @@ -1961,7 +1954,7 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 pin_num, if (pin_num > MAX_GPIO_PIN_NUMBER) return -EINVAL; - if (p_gpio_config == NULL) + if (!p_gpio_config) return -EINVAL; total_len = sizeof(struct sms_msg_hdr) + (sizeof(u32) * 6); diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c index a772976cfe26..f96968c11312 100644 --- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c +++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c @@ -238,6 +238,8 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) tpg->color_enc = TGP_COLOR_ENC_RGB; break; case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_Y10: + case V4L2_PIX_FMT_Y12: case V4L2_PIX_FMT_Y16: case V4L2_PIX_FMT_Y16_BE: tpg->color_enc = TGP_COLOR_ENC_LUMA; @@ -352,6 +354,8 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_YUV444: case V4L2_PIX_FMT_YUV555: case V4L2_PIX_FMT_YUV565: + case V4L2_PIX_FMT_Y10: + case V4L2_PIX_FMT_Y12: case V4L2_PIX_FMT_Y16: case V4L2_PIX_FMT_Y16_BE: tpg->twopixelsize[0] = 2 * 2; @@ -1056,6 +1060,14 @@ static void gen_twopix(struct tpg_data *tpg, case V4L2_PIX_FMT_GREY: buf[0][offset] = r_y_h; break; + case V4L2_PIX_FMT_Y10: + buf[0][offset] = (r_y_h << 2) & 0xff; + buf[0][offset+1] = r_y_h >> 6; + break; + case V4L2_PIX_FMT_Y12: + buf[0][offset] = (r_y_h << 4) & 0xff; + buf[0][offset+1] = r_y_h >> 4; + break; case V4L2_PIX_FMT_Y16: /* * Ideally both bytes should be set to r_y_h, but then you won't diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index 18e4230865be..3ddd44e1ee77 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -329,9 +329,9 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, return 0; } -static void dvb_dmxdev_filter_timeout(unsigned long data) +static void dvb_dmxdev_filter_timeout(struct timer_list *t) { - struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data; + struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer); dmxdevfilter->buffer.error = -ETIMEDOUT; spin_lock_irq(&dmxdevfilter->dev->lock); @@ -346,8 +346,6 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) del_timer(&dmxdevfilter->timer); if (para->timeout) { - dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout; - dmxdevfilter->timer.data = (unsigned long)dmxdevfilter; dmxdevfilter->timer.expires = jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000; add_timer(&dmxdevfilter->timer); @@ -754,7 +752,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file) dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); dmxdevfilter->type = DMXDEV_TYPE_NONE; dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); - init_timer(&dmxdevfilter->timer); + timer_setup(&dmxdevfilter->timer, dvb_dmxdev_filter_timeout, 0); dvbdev->users++; diff --git a/drivers/media/dvb-core/dmxdev.h b/drivers/media/dvb-core/dmxdev.h index 054fd4eb6192..5e795f5f0f41 100644 --- a/drivers/media/dvb-core/dmxdev.h +++ b/drivers/media/dvb-core/dmxdev.h @@ -36,12 +36,33 @@ #include "demux.h" #include "dvb_ringbuffer.h" +/** + * enum dmxdev_type - type of demux filter type. + * + * @DMXDEV_TYPE_NONE: no filter set. + * @DMXDEV_TYPE_SEC: section filter. + * @DMXDEV_TYPE_PES: Program Elementary Stream (PES) filter. + */ enum dmxdev_type { DMXDEV_TYPE_NONE, DMXDEV_TYPE_SEC, DMXDEV_TYPE_PES, }; +/** + * enum dmxdev_state - state machine for the dmxdev. + * + * @DMXDEV_STATE_FREE: indicates that the filter is freed. + * @DMXDEV_STATE_ALLOCATED: indicates that the filter was allocated + * to be used. + * @DMXDEV_STATE_SET: indicates that the filter parameters are set. + * @DMXDEV_STATE_GO: indicates that the filter is running. + * @DMXDEV_STATE_DONE: indicates that a packet was already filtered + * and the filter is now disabled. + * Set only if %DMX_ONESHOT. See + * &dmx_sct_filter_params. + * @DMXDEV_STATE_TIMEDOUT: Indicates a timeout condition. + */ enum dmxdev_state { DMXDEV_STATE_FREE, DMXDEV_STATE_ALLOCATED, @@ -51,12 +72,49 @@ enum dmxdev_state { DMXDEV_STATE_TIMEDOUT }; +/** + * struct dmxdev_feed - digital TV dmxdev feed + * + * @pid: Program ID to be filtered + * @ts: pointer to &struct dmx_ts_feed + * @next: &struct list_head pointing to the next feed. + */ + struct dmxdev_feed { u16 pid; struct dmx_ts_feed *ts; struct list_head next; }; +/** + * struct dmxdev_filter - digital TV dmxdev filter + * + * @filter: a dmxdev filter. Currently used only for section filter: + * if the filter is Section, it contains a + * &struct dmx_section_filter @sec pointer. + * @feed: a dmxdev feed. Depending on the feed type, it can be: + * for TS feed: a &struct list_head @ts list of TS and PES + * feeds; + * for section feed: a &struct dmx_section_feed @sec pointer. + * @params: dmxdev filter parameters. Depending on the feed type, it + * can be: + * for section filter: a &struct dmx_sct_filter_params @sec + * embedded struct; + * for a TS filter: a &struct dmx_pes_filter_params @pes + * embedded struct. + * @type: type of the dmxdev filter, as defined by &enum dmxdev_type. + * @state: state of the dmxdev filter, as defined by &enum dmxdev_state. + * @dev: pointer to &struct dmxdev. + * @buffer: an embedded &struct dvb_ringbuffer buffer. + * @mutex: protects the access to &struct dmxdev_filter. + * @timer: &struct timer_list embedded timer, used to check for + * feed timeouts. + * Only for section filter. + * @todo: index for the @secheader. + * Only for section filter. + * @secheader: buffer cache to parse the section header. + * Only for section filter. + */ struct dmxdev_filter { union { struct dmx_section_filter *sec; @@ -86,7 +144,23 @@ struct dmxdev_filter { u8 secheader[3]; }; - +/** + * struct dmxdev - Describes a digital TV demux device. + * + * @dvbdev: pointer to &struct dvb_device associated with + * the demux device node. + * @dvr_dvbdev: pointer to &struct dvb_device associated with + * the dvr device node. + * @filter: pointer to &struct dmxdev_filter. + * @demux: pointer to &struct dmx_demux. + * @filternum: number of filters. + * @capabilities: demux capabilities as defined by &enum dmx_demux_caps. + * @exit: flag to indicate that the demux is being released. + * @dvr_orig_fe: pointer to &struct dmx_frontend. + * @dvr_buffer: embedded &struct dvb_ringbuffer for DVB output. + * @mutex: protects the usage of this structure. + * @lock: protects access to &dmxdev->filter->data. + */ struct dmxdev { struct dvb_device *dvbdev; struct dvb_device *dvr_dvbdev; @@ -108,8 +182,20 @@ struct dmxdev { spinlock_t lock; }; +/** + * dvb_dmxdev_init - initializes a digital TV demux and registers both demux + * and DVR devices. + * + * @dmxdev: pointer to &struct dmxdev. + * @adap: pointer to &struct dvb_adapter. + */ +int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *adap); -int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *); +/** + * dvb_dmxdev_release - releases a digital TV demux and unregisters it. + * + * @dmxdev: pointer to &struct dmxdev. + */ void dvb_dmxdev_release(struct dmxdev *dmxdev); #endif /* _DMXDEV_H_ */ diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c index 95b3723282f4..d48b61eb01f4 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb-core/dvb_ca_en50221.c @@ -206,7 +206,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, * @hlen: Number of bytes in haystack. * @needle: Buffer to find. * @nlen: Number of bytes in needle. - * @return Pointer into haystack needle was found at, or NULL if not found. + * return: Pointer into haystack needle was found at, or NULL if not found. */ static char *findstr(char *haystack, int hlen, char *needle, int nlen) { @@ -226,7 +226,7 @@ static char *findstr(char *haystack, int hlen, char *needle, int nlen) /* ************************************************************************** */ /* EN50221 physical interface functions */ -/** +/* * dvb_ca_en50221_check_camstatus - Check CAM status. */ static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot) @@ -275,9 +275,9 @@ static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot) * @ca: CA instance. * @slot: Slot on interface. * @waitfor: Flags to wait for. - * @timeout_ms: Timeout in milliseconds. + * @timeout_hz: Timeout in milliseconds. * - * @return 0 on success, nonzero on error. + * return: 0 on success, nonzero on error. */ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, u8 waitfor, int timeout_hz) @@ -325,7 +325,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, * @ca: CA instance. * @slot: Slot id. * - * @return 0 on success, nonzero on failure. + * return: 0 on success, nonzero on failure. */ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) { @@ -397,11 +397,11 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) * @ca: CA instance. * @slot: Slot id. * @address: Address to read from. Updated. - * @tupleType: Tuple id byte. Updated. - * @tupleLength: Tuple length. Updated. + * @tuple_type: Tuple id byte. Updated. + * @tuple_length: Tuple length. Updated. * @tuple: Dest buffer for tuple (must be 256 bytes). Updated. * - * @return 0 on success, nonzero on error. + * return: 0 on success, nonzero on error. */ static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot, int *address, int *tuple_type, @@ -455,7 +455,7 @@ static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot, * @ca: CA instance. * @slot: Slot id. * - * @return 0 on success, <0 on failure. + * return: 0 on success, <0 on failure. */ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot) { @@ -632,10 +632,11 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot) * @ca: CA instance. * @slot: Slot to read from. * @ebuf: If non-NULL, the data will be written to this buffer. If NULL, - * the data will be added into the buffering system as a normal fragment. + * the data will be added into the buffering system as a normal + * fragment. * @ecount: Size of ebuf. Ignored if ebuf is NULL. * - * @return Number of bytes read, or < 0 on error + * return: Number of bytes read, or < 0 on error */ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 *ebuf, int ecount) @@ -784,11 +785,11 @@ exit: * * @ca: CA instance. * @slot: Slot to write to. - * @ebuf: The data in this buffer is treated as a complete link-level packet to - * be written. - * @count: Size of ebuf. + * @buf: The data in this buffer is treated as a complete link-level packet to + * be written. + * @bytes_write: Size of ebuf. * - * @return Number of bytes written, or < 0 on error. + * return: Number of bytes written, or < 0 on error. */ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 *buf, int bytes_write) @@ -933,7 +934,7 @@ static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot) /** * dvb_ca_en50221_camchange_irq - A CAMCHANGE IRQ has occurred. * - * @ca: CA instance. + * @pubca: CA instance. * @slot: Slot concerned. * @change_type: One of the DVB_CA_CAMCHANGE_* values. */ @@ -963,7 +964,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq); /** * dvb_ca_en50221_camready_irq - A CAMREADY IRQ has occurred. * - * @ca: CA instance. + * @pubca: CA instance. * @slot: Slot concerned. */ void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot) @@ -983,7 +984,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camready_irq); /** * dvb_ca_en50221_frda_irq - An FR or DA IRQ has occurred. * - * @ca: CA instance. + * @pubca: CA instance. * @slot: Slot concerned. */ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot) @@ -1091,7 +1092,7 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) * * @ca: CA instance. * @slot: Slot to process. - * @return: 0 .. no change + * return:: 0 .. no change * 1 .. CAM state changed */ @@ -1296,7 +1297,7 @@ static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca, mutex_unlock(&sl->slot_lock); } -/** +/* * Kernel thread which monitors CA slots for CAM changes, and performs data * transfers. */ @@ -1336,12 +1337,11 @@ static int dvb_ca_en50221_thread(void *data) * Real ioctl implementation. * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them. * - * @inode: Inode concerned. * @file: File concerned. * @cmd: IOCTL command. - * @arg: Associated argument. + * @parg: Associated argument. * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ static int dvb_ca_en50221_io_do_ioctl(struct file *file, unsigned int cmd, void *parg) @@ -1420,12 +1420,11 @@ out_unlock: /** * Wrapper for ioctl implementation. * - * @inode: Inode concerned. * @file: File concerned. * @cmd: IOCTL command. * @arg: Associated argument. * - * @return 0 on success, <0 on error. + * return: 0 on success, <0 on error. */ static long dvb_ca_en50221_io_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -1441,7 +1440,7 @@ static long dvb_ca_en50221_io_ioctl(struct file *file, * @count: Size of source buffer. * @ppos: Position in file (ignored). * - * @return Number of bytes read, or <0 on error. + * return: Number of bytes read, or <0 on error. */ static ssize_t dvb_ca_en50221_io_write(struct file *file, const char __user *buf, size_t count, @@ -1536,7 +1535,7 @@ exit: return status; } -/** +/* * Condition for waking up in dvb_ca_en50221_io_read_condition */ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, @@ -1593,7 +1592,7 @@ nextslot: * @count: Size of destination buffer. * @ppos: Position in file (ignored). * - * @return Number of bytes read, or <0 on error. + * return: Number of bytes read, or <0 on error. */ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) @@ -1702,7 +1701,7 @@ exit: * @inode: Inode concerned. * @file: File concerned. * - * @return 0 on success, <0 on failure. + * return: 0 on success, <0 on failure. */ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) { @@ -1752,7 +1751,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) * @inode: Inode concerned. * @file: File concerned. * - * @return 0 on success, <0 on failure. + * return: 0 on success, <0 on failure. */ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) { @@ -1781,7 +1780,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) * @file: File concerned. * @wait: poll wait table. * - * @return Standard poll mask. + * return: Standard poll mask. */ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) { @@ -1838,11 +1837,11 @@ static const struct dvb_device dvbdev_ca = { * Initialise a new DVB CA EN50221 interface device. * * @dvb_adapter: DVB adapter to attach the new CA device to. - * @ca: The dvb_ca instance. + * @pubca: The dvb_ca instance. * @flags: Flags describing the CA device (DVB_CA_FLAG_*). * @slot_count: Number of slots supported. * - * @return 0 on success, nonzero on failure + * return: 0 on success, nonzero on failure */ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221 *pubca, int flags, int slot_count) @@ -1929,8 +1928,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_init); /** * Release a DVB CA EN50221 interface device. * - * @ca_dev: The dvb_device_t instance for the CA device. - * @ca: The associated dvb_ca instance. + * @pubca: The associated dvb_ca instance. */ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca) { diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c index 6628f80d184f..acade7543b82 100644 --- a/drivers/media/dvb-core/dvb_demux.c +++ b/drivers/media/dvb-core/dvb_demux.c @@ -223,10 +223,10 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) * when the second packet arrives. * * Fix: - * when demux is started, let feed->pusi_seen = 0 to + * when demux is started, let feed->pusi_seen = false to * prevent initial feeding of garbage from the end of * previous section. When you for the first time see PUSI=1 - * then set feed->pusi_seen = 1 + * then set feed->pusi_seen = true */ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const u8 *buf, u8 len) @@ -318,10 +318,10 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, */ #endif /* - * Discontinuity detected. Reset pusi_seen = 0 to + * Discontinuity detected. Reset pusi_seen to * stop feeding of suspicious data until next PUSI=1 arrives */ - feed->pusi_seen = 0; + feed->pusi_seen = false; dvb_dmx_swfilter_section_new(feed); } @@ -335,8 +335,8 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, dvb_dmx_swfilter_section_copy_dump(feed, before, before_len); - /* before start of new section, set pusi_seen = 1 */ - feed->pusi_seen = 1; + /* before start of new section, set pusi_seen */ + feed->pusi_seen = true; dvb_dmx_swfilter_section_new(feed); dvb_dmx_swfilter_section_copy_dump(feed, after, after_len); @@ -367,6 +367,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, else feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts); } + /* Used only on full-featured devices */ if (feed->ts_type & TS_DECODER) if (feed->demux->write_to_decoder) feed->demux->write_to_decoder(feed, buf, 188); @@ -898,14 +899,14 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed) return; do { sf = &f->filter; - doneq = 0; + doneq = false; for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) { mode = sf->filter_mode[i]; mask = sf->filter_mask[i]; f->maskandmode[i] = mask & mode; doneq |= f->maskandnotmode[i] = mask & ~mode; } - f->doneq = doneq ? 1 : 0; + f->doneq = doneq ? true : false; } while ((f = f->next)); } diff --git a/drivers/media/dvb-core/dvb_demux.h b/drivers/media/dvb-core/dvb_demux.h index 6f572ca8d339..cc048f09aa85 100644 --- a/drivers/media/dvb-core/dvb_demux.h +++ b/drivers/media/dvb-core/dvb_demux.h @@ -26,15 +26,33 @@ #include "demux.h" -#define DMX_TYPE_TS 0 -#define DMX_TYPE_SEC 1 -#define DMX_TYPE_PES 2 +/** + * enum dvb_dmx_filter_type - type of demux feed. + * + * @DMX_TYPE_TS: feed is in TS mode. + * @DMX_TYPE_SEC: feed is in Section mode. + */ +enum dvb_dmx_filter_type { + DMX_TYPE_TS, + DMX_TYPE_SEC, +}; -#define DMX_STATE_FREE 0 -#define DMX_STATE_ALLOCATED 1 -#define DMX_STATE_SET 2 -#define DMX_STATE_READY 3 -#define DMX_STATE_GO 4 +/** + * enum dvb_dmx_state - state machine for a demux filter. + * + * @DMX_STATE_FREE: indicates that the filter is freed. + * @DMX_STATE_ALLOCATED: indicates that the filter was allocated + * to be used. + * @DMX_STATE_READY: indicates that the filter is ready + * to be used. + * @DMX_STATE_GO: indicates that the filter is running. + */ +enum dvb_dmx_state { + DMX_STATE_FREE, + DMX_STATE_ALLOCATED, + DMX_STATE_READY, + DMX_STATE_GO, +}; #define DVB_DEMUX_MASK_MAX 18 @@ -42,24 +60,66 @@ #define SPEED_PKTS_INTERVAL 50000 +/** + * struct dvb_demux_filter - Describes a DVB demux section filter. + * + * @filter: Section filter as defined by &struct dmx_section_filter. + * @maskandmode: logical ``and`` bit mask. + * @maskandnotmode: logical ``and not`` bit mask. + * @doneq: flag that indicates when a filter is ready. + * @next: pointer to the next section filter. + * @feed: &struct dvb_demux_feed pointer. + * @index: index of the used demux filter. + * @state: state of the filter as described by &enum dvb_dmx_state. + * @type: type of the filter as described + * by &enum dvb_dmx_filter_type. + */ + struct dvb_demux_filter { struct dmx_section_filter filter; u8 maskandmode[DMX_MAX_FILTER_SIZE]; u8 maskandnotmode[DMX_MAX_FILTER_SIZE]; - int doneq; + bool doneq; struct dvb_demux_filter *next; struct dvb_demux_feed *feed; int index; - int state; - int type; + enum dvb_dmx_state state; + enum dvb_dmx_filter_type type; + /* private: used only by av7110 */ u16 hw_handle; - struct timer_list timer; }; -#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head) - +/** + * struct dvb_demux_feed - describes a DVB field + * + * @feed: a digital TV feed. It can either be a TS or a section feed: + * if the feed is TS, it contains &struct dvb_ts_feed @ts; + * if the feed is section, it contains + * &struct dmx_section_feed @sec. + * @cb: digital TV callbacks. depending on the feed type, it can be: + * if the feed is TS, it contains a dmx_ts_cb() @ts callback; + * if the feed is section, it contains a dmx_section_cb() @sec + * callback. + * + * @demux: pointer to &struct dvb_demux. + * @priv: private data that can optionally be used by a DVB driver. + * @type: type of the filter, as defined by &enum dvb_dmx_filter_type. + * @state: state of the filter as defined by &enum dvb_dmx_state. + * @pid: PID to be filtered. + * @timeout: feed timeout. + * @filter: pointer to &struct dvb_demux_filter. + * @ts_type: type of TS, as defined by &enum ts_filter_type. + * @pes_type: type of PES, as defined by &enum dmx_ts_pes. + * @cc: MPEG-TS packet continuity counter + * @pusi_seen: if true, indicates that a discontinuity was detected. + * it is used to prevent feeding of garbage from previous section. + * @peslen: length of the PES (Packet Elementary Stream). + * @list_head: head for the list of digital TV demux feeds. + * @index: a unique index for each feed. Can be used as hardware + * pid filter index. + */ struct dvb_demux_feed { union { struct dmx_ts_feed ts; @@ -73,25 +133,63 @@ struct dvb_demux_feed { struct dvb_demux *demux; void *priv; - int type; - int state; + enum dvb_dmx_filter_type type; + enum dvb_dmx_state state; u16 pid; ktime_t timeout; struct dvb_demux_filter *filter; - int ts_type; + enum ts_filter_type ts_type; enum dmx_ts_pes pes_type; int cc; - int pusi_seen; /* prevents feeding of garbage from previous section */ + bool pusi_seen; u16 peslen; struct list_head list_head; - unsigned int index; /* a unique index for each feed (can be used as hardware pid filter index) */ + unsigned int index; }; +/** + * struct dvb_demux - represents a digital TV demux + * @dmx: embedded &struct dmx_demux with demux capabilities + * and callbacks. + * @priv: private data that can optionally be used by + * a DVB driver. + * @filternum: maximum amount of DVB filters. + * @feednum: maximum amount of DVB feeds. + * @start_feed: callback routine to be called in order to start + * a DVB feed. + * @stop_feed: callback routine to be called in order to stop + * a DVB feed. + * @write_to_decoder: callback routine to be called if the feed is TS and + * it is routed to an A/V decoder, when a new TS packet + * is received. + * Used only on av7110-av.c. + * @check_crc32: callback routine to check CRC. If not initialized, + * dvb_demux will use an internal one. + * @memcopy: callback routine to memcopy received data. + * If not initialized, dvb_demux will default to memcpy(). + * @users: counter for the number of demux opened file descriptors. + * Currently, it is limited to 10 users. + * @filter: pointer to &struct dvb_demux_filter. + * @feed: pointer to &struct dvb_demux_feed. + * @frontend_list: &struct list_head with frontends used by the demux. + * @pesfilter: array of &struct dvb_demux_feed with the PES types + * that will be filtered. + * @pids: list of filtered program IDs. + * @feed_list: &struct list_head with feeds. + * @tsbuf: temporary buffer used internally to store TS packets. + * @tsbufp: temporary buffer index used internally. + * @mutex: pointer to &struct mutex used to protect feed set + * logic. + * @lock: pointer to &spinlock_t, used to protect buffer handling. + * @cnt_storage: buffer used for TS/TEI continuity check. + * @speed_last_time: &ktime_t used for TS speed check. + * @speed_pkts_cnt: packets count used for TS speed check. + */ struct dvb_demux { struct dmx_demux dmx; void *priv; @@ -115,8 +213,6 @@ struct dvb_demux { struct dvb_demux_feed *pesfilter[DMX_PES_OTHER]; u16 pids[DMX_PES_OTHER]; - int playing; - int recording; #define DMX_MAX_PID 0x2000 struct list_head feed_list; @@ -130,15 +226,119 @@ struct dvb_demux { ktime_t speed_last_time; /* for TS speed check */ uint32_t speed_pkts_cnt; /* for TS speed check */ + + /* private: used only on av7110 */ + int playing; + int recording; }; -int dvb_dmx_init(struct dvb_demux *dvbdemux); -void dvb_dmx_release(struct dvb_demux *dvbdemux); -void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, +/** + * dvb_dmx_init - initialize a digital TV demux struct. + * + * @demux: &struct dvb_demux to be initialized. + * + * Before being able to register a digital TV demux struct, drivers + * should call this routine. On its typical usage, some fields should + * be initialized at the driver before calling it. + * + * A typical usecase is:: + * + * dvb->demux.dmx.capabilities = + * DMX_TS_FILTERING | DMX_SECTION_FILTERING | + * DMX_MEMORY_BASED_FILTERING; + * dvb->demux.priv = dvb; + * dvb->demux.filternum = 256; + * dvb->demux.feednum = 256; + * dvb->demux.start_feed = driver_start_feed; + * dvb->demux.stop_feed = driver_stop_feed; + * ret = dvb_dmx_init(&dvb->demux); + * if (ret < 0) + * return ret; + */ +int dvb_dmx_init(struct dvb_demux *demux); + +/** + * dvb_dmx_release - releases a digital TV demux internal buffers. + * + * @demux: &struct dvb_demux to be released. + * + * The DVB core internally allocates data at @demux. This routine + * releases those data. Please notice that the struct itelf is not + * released, as it can be embedded on other structs. + */ +void dvb_dmx_release(struct dvb_demux *demux); + +/** + * dvb_dmx_swfilter_packets - use dvb software filter for a buffer with + * multiple MPEG-TS packets with 188 bytes each. + * + * @demux: pointer to &struct dvb_demux + * @buf: buffer with data to be filtered + * @count: number of MPEG-TS packets with size of 188. + * + * The routine will discard a DVB packet that don't start with 0x47. + * + * Use this routine if the DVB demux fills MPEG-TS buffers that are + * already aligned. + * + * NOTE: The @buf size should have size equal to ``count * 188``. + */ +void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count); + +/** + * dvb_dmx_swfilter - use dvb software filter for a buffer with + * multiple MPEG-TS packets with 188 bytes each. + * + * @demux: pointer to &struct dvb_demux + * @buf: buffer with data to be filtered + * @count: number of MPEG-TS packets with size of 188. + * + * If a DVB packet doesn't start with 0x47, it will seek for the first + * byte that starts with 0x47. + * + * Use this routine if the DVB demux fill buffers that may not start with + * a packet start mark (0x47). + * + * NOTE: The @buf size should have size equal to ``count * 188``. + */ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count); + +/** + * dvb_dmx_swfilter_204 - use dvb software filter for a buffer with + * multiple MPEG-TS packets with 204 bytes each. + * + * @demux: pointer to &struct dvb_demux + * @buf: buffer with data to be filtered + * @count: number of MPEG-TS packets with size of 204. + * + * If a DVB packet doesn't start with 0x47, it will seek for the first + * byte that starts with 0x47. + * + * Use this routine if the DVB demux fill buffers that may not start with + * a packet start mark (0x47). + * + * NOTE: The @buf size should have size equal to ``count * 204``. + */ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count); + +/** + * dvb_dmx_swfilter_raw - make the raw data available to userspace without + * filtering + * + * @demux: pointer to &struct dvb_demux + * @buf: buffer with data + * @count: number of packets to be passed. The actual size of each packet + * depends on the &dvb_demux->feed->cb.ts logic. + * + * Use it if the driver needs to deliver the raw payload to userspace without + * passing through the kernel demux. That is meant to support some + * delivery systems that aren't based on MPEG-TS. + * + * This function relies on &dvb_demux->feed->cb.ts to actually handle the + * buffer. + */ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count); diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 9139d01ba7ed..2afaa8226342 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -145,15 +145,13 @@ static void __dvb_frontend_free(struct dvb_frontend *fe) { struct dvb_frontend_private *fepriv = fe->frontend_priv; - if (!fepriv) - return; - - dvb_free_device(fepriv->dvbdev); + if (fepriv) + dvb_free_device(fepriv->dvbdev); dvb_frontend_invoke_release(fe, fe->ops.release); - kfree(fepriv); - fe->frontend_priv = NULL; + if (fepriv) + kfree(fepriv); } static void dvb_frontend_free(struct kref *ref) @@ -371,11 +369,14 @@ static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepr } /** - * Performs automatic twiddling of frontend parameters. + * dvb_frontend_swzigzag_autotune - Performs automatic twiddling of frontend + * parameters. * - * @param fe The frontend concerned. - * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT - * @returns Number of complete iterations that have been performed. + * @fe: The frontend concerned. + * @check_wrapped: Checks if an iteration has completed. + * DO NOT SET ON THE FIRST ATTEMPT. + * + * return: Number of complete iterations that have been performed. */ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped) { @@ -951,8 +952,6 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe) memset(c, 0, offsetof(struct dtv_frontend_properties, strength)); c->delivery_system = delsys; - c->state = DTV_CLEAR; - dev_dbg(fe->dvb->device, "%s: Clearing cache for delivery system %d\n", __func__, c->delivery_system); @@ -1109,39 +1108,6 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0), }; -static void dtv_property_dump(struct dvb_frontend *fe, - bool is_set, - struct dtv_property *tvp) -{ - int i; - - if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { - dev_warn(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x undefined\n", - __func__, - is_set ? "SET" : "GET", - tvp->cmd); - return; - } - - dev_dbg(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x (%s)\n", __func__, - is_set ? "SET" : "GET", - tvp->cmd, - dtv_cmds[tvp->cmd].name); - - if (dtv_cmds[tvp->cmd].buffer) { - dev_dbg(fe->dvb->device, "%s: tvp.u.buffer.len = 0x%02x\n", - __func__, tvp->u.buffer.len); - - for(i = 0; i < tvp->u.buffer.len; i++) - dev_dbg(fe->dvb->device, - "%s: tvp.u.buffer.data[0x%02x] = 0x%02x\n", - __func__, i, tvp->u.buffer.data[i]); - } else { - dev_dbg(fe->dvb->device, "%s: tvp.u.data = 0x%08x\n", __func__, - tvp->u.data); - } -} - /* Synchronise the legacy tuning parameters into the cache, so that demodulator * drivers can use a single set_frontend tuning function, regardless of whether * it's being used for the legacy or new API, reducing code and complexity. @@ -1290,7 +1256,7 @@ dtv_property_legacy_params_sync(struct dvb_frontend *fe, * dtv_get_frontend - calls a callback for retrieving DTV parameters * @fe: struct dvb_frontend pointer * @c: struct dtv_frontend_properties pointer (DVBv5 cache) - * @p_out struct dvb_frontend_parameters pointer (DVBv3 FE struct) + * @p_out: struct dvb_frontend_parameters pointer (DVBv3 FE struct) * * This routine calls either the DVBv3 or DVBv5 get_frontend call. * If c is not null, it will update the DVBv5 cache struct pointed by it. @@ -1315,17 +1281,15 @@ static int dtv_get_frontend(struct dvb_frontend *fe, return 0; } -static int dvb_frontend_ioctl_legacy(struct file *file, - unsigned int cmd, void *parg); -static int dvb_frontend_ioctl_properties(struct file *file, - unsigned int cmd, void *parg); +static int dvb_frontend_handle_ioctl(struct file *file, + unsigned int cmd, void *parg); static int dtv_property_process_get(struct dvb_frontend *fe, const struct dtv_frontend_properties *c, struct dtv_property *tvp, struct file *file) { - int r, ncaps; + int ncaps; switch(tvp->cmd) { case DTV_ENUM_DELSYS: @@ -1536,14 +1500,18 @@ static int dtv_property_process_get(struct dvb_frontend *fe, return -EINVAL; } - /* Allow the frontend to override outgoing properties */ - if (fe->ops.get_property) { - r = fe->ops.get_property(fe, tvp); - if (r < 0) - return r; - } - - dtv_property_dump(fe, false, tvp); + if (!dtv_cmds[tvp->cmd].buffer) + dev_dbg(fe->dvb->device, + "%s: GET cmd 0x%08x (%s) = 0x%08x\n", + __func__, tvp->cmd, dtv_cmds[tvp->cmd].name, + tvp->u.data); + else + dev_dbg(fe->dvb->device, + "%s: GET cmd 0x%08x (%s) len %d: %*ph\n", + __func__, + tvp->cmd, dtv_cmds[tvp->cmd].name, + tvp->u.buffer.len, + tvp->u.buffer.len, tvp->u.buffer.data); return 0; } @@ -1766,23 +1734,36 @@ static int dvbv3_set_delivery_system(struct dvb_frontend *fe) return emulate_delivery_system(fe, delsys); } +/** + * dtv_property_process_set - Sets a single DTV property + * @fe: Pointer to &struct dvb_frontend + * @file: Pointer to &struct file + * @cmd: Digital TV command + * @data: An unsigned 32-bits number + * + * This routine assigns the property + * value to the corresponding member of + * &struct dtv_frontend_properties + * + * Returns: + * Zero on success, negative errno on failure. + */ static int dtv_property_process_set(struct dvb_frontend *fe, - struct dtv_property *tvp, - struct file *file) + struct file *file, + u32 cmd, u32 data) { int r = 0; struct dtv_frontend_properties *c = &fe->dtv_property_cache; - /* Allow the frontend to validate incoming properties */ - if (fe->ops.set_property) { - r = fe->ops.set_property(fe, tvp); - if (r < 0) - return r; - } - - dtv_property_dump(fe, true, tvp); - - switch(tvp->cmd) { + /** Dump DTV command name and value*/ + if (!cmd || cmd > DTV_MAX_COMMAND) + dev_warn(fe->dvb->device, "%s: SET cmd 0x%08x undefined\n", + __func__, cmd); + else + dev_dbg(fe->dvb->device, + "%s: SET cmd 0x%08x (%s) to 0x%08x\n", + __func__, cmd, dtv_cmds[cmd].name, data); + switch (cmd) { case DTV_CLEAR: /* * Reset a cache of data specific to the frontend here. This does @@ -1791,144 +1772,144 @@ static int dtv_property_process_set(struct dvb_frontend *fe, dvb_frontend_clear_cache(fe); break; case DTV_TUNE: - /* interpret the cache of data, build either a traditional frontend - * tunerequest so we can pass validation in the FE_SET_FRONTEND - * ioctl. + /* + * Use the cached Digital TV properties to tune the + * frontend */ - c->state = tvp->cmd; - dev_dbg(fe->dvb->device, "%s: Finalised property cache\n", - __func__); + dev_dbg(fe->dvb->device, + "%s: Setting the frontend from property cache\n", + __func__); r = dtv_set_frontend(fe); break; case DTV_FREQUENCY: - c->frequency = tvp->u.data; + c->frequency = data; break; case DTV_MODULATION: - c->modulation = tvp->u.data; + c->modulation = data; break; case DTV_BANDWIDTH_HZ: - c->bandwidth_hz = tvp->u.data; + c->bandwidth_hz = data; break; case DTV_INVERSION: - c->inversion = tvp->u.data; + c->inversion = data; break; case DTV_SYMBOL_RATE: - c->symbol_rate = tvp->u.data; + c->symbol_rate = data; break; case DTV_INNER_FEC: - c->fec_inner = tvp->u.data; + c->fec_inner = data; break; case DTV_PILOT: - c->pilot = tvp->u.data; + c->pilot = data; break; case DTV_ROLLOFF: - c->rolloff = tvp->u.data; + c->rolloff = data; break; case DTV_DELIVERY_SYSTEM: - r = dvbv5_set_delivery_system(fe, tvp->u.data); + r = dvbv5_set_delivery_system(fe, data); break; case DTV_VOLTAGE: - c->voltage = tvp->u.data; - r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE, + c->voltage = data; + r = dvb_frontend_handle_ioctl(file, FE_SET_VOLTAGE, (void *)c->voltage); break; case DTV_TONE: - c->sectone = tvp->u.data; - r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE, + c->sectone = data; + r = dvb_frontend_handle_ioctl(file, FE_SET_TONE, (void *)c->sectone); break; case DTV_CODE_RATE_HP: - c->code_rate_HP = tvp->u.data; + c->code_rate_HP = data; break; case DTV_CODE_RATE_LP: - c->code_rate_LP = tvp->u.data; + c->code_rate_LP = data; break; case DTV_GUARD_INTERVAL: - c->guard_interval = tvp->u.data; + c->guard_interval = data; break; case DTV_TRANSMISSION_MODE: - c->transmission_mode = tvp->u.data; + c->transmission_mode = data; break; case DTV_HIERARCHY: - c->hierarchy = tvp->u.data; + c->hierarchy = data; break; case DTV_INTERLEAVING: - c->interleaving = tvp->u.data; + c->interleaving = data; break; /* ISDB-T Support here */ case DTV_ISDBT_PARTIAL_RECEPTION: - c->isdbt_partial_reception = tvp->u.data; + c->isdbt_partial_reception = data; break; case DTV_ISDBT_SOUND_BROADCASTING: - c->isdbt_sb_mode = tvp->u.data; + c->isdbt_sb_mode = data; break; case DTV_ISDBT_SB_SUBCHANNEL_ID: - c->isdbt_sb_subchannel = tvp->u.data; + c->isdbt_sb_subchannel = data; break; case DTV_ISDBT_SB_SEGMENT_IDX: - c->isdbt_sb_segment_idx = tvp->u.data; + c->isdbt_sb_segment_idx = data; break; case DTV_ISDBT_SB_SEGMENT_COUNT: - c->isdbt_sb_segment_count = tvp->u.data; + c->isdbt_sb_segment_count = data; break; case DTV_ISDBT_LAYER_ENABLED: - c->isdbt_layer_enabled = tvp->u.data; + c->isdbt_layer_enabled = data; break; case DTV_ISDBT_LAYERA_FEC: - c->layer[0].fec = tvp->u.data; + c->layer[0].fec = data; break; case DTV_ISDBT_LAYERA_MODULATION: - c->layer[0].modulation = tvp->u.data; + c->layer[0].modulation = data; break; case DTV_ISDBT_LAYERA_SEGMENT_COUNT: - c->layer[0].segment_count = tvp->u.data; + c->layer[0].segment_count = data; break; case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: - c->layer[0].interleaving = tvp->u.data; + c->layer[0].interleaving = data; break; case DTV_ISDBT_LAYERB_FEC: - c->layer[1].fec = tvp->u.data; + c->layer[1].fec = data; break; case DTV_ISDBT_LAYERB_MODULATION: - c->layer[1].modulation = tvp->u.data; + c->layer[1].modulation = data; break; case DTV_ISDBT_LAYERB_SEGMENT_COUNT: - c->layer[1].segment_count = tvp->u.data; + c->layer[1].segment_count = data; break; case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: - c->layer[1].interleaving = tvp->u.data; + c->layer[1].interleaving = data; break; case DTV_ISDBT_LAYERC_FEC: - c->layer[2].fec = tvp->u.data; + c->layer[2].fec = data; break; case DTV_ISDBT_LAYERC_MODULATION: - c->layer[2].modulation = tvp->u.data; + c->layer[2].modulation = data; break; case DTV_ISDBT_LAYERC_SEGMENT_COUNT: - c->layer[2].segment_count = tvp->u.data; + c->layer[2].segment_count = data; break; case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: - c->layer[2].interleaving = tvp->u.data; + c->layer[2].interleaving = data; break; /* Multistream support */ case DTV_STREAM_ID: case DTV_DVBT2_PLP_ID_LEGACY: - c->stream_id = tvp->u.data; + c->stream_id = data; break; /* ATSC-MH */ case DTV_ATSCMH_PARADE_ID: - fe->dtv_property_cache.atscmh_parade_id = tvp->u.data; + fe->dtv_property_cache.atscmh_parade_id = data; break; case DTV_ATSCMH_RS_FRAME_ENSEMBLE: - fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data; + fe->dtv_property_cache.atscmh_rs_frame_ensemble = data; break; case DTV_LNA: - c->lna = tvp->u.data; + c->lna = data; if (fe->ops.set_lna) r = fe->ops.set_lna(fe); if (r < 0) @@ -1942,14 +1923,12 @@ static int dtv_property_process_set(struct dvb_frontend *fe, return r; } -static int dvb_frontend_ioctl(struct file *file, - unsigned int cmd, void *parg) +static int dvb_frontend_ioctl(struct file *file, unsigned int cmd, void *parg) { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; - int err = -EOPNOTSUPP; + int err; dev_dbg(fe->dvb->device, "%s: (%d)\n", __func__, _IOC_NR(cmd)); if (down_interruptible(&fepriv->sem)) @@ -1960,109 +1939,33 @@ static int dvb_frontend_ioctl(struct file *file, return -ENODEV; } - if ((file->f_flags & O_ACCMODE) == O_RDONLY && - (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT || - cmd == FE_DISEQC_RECV_SLAVE_REPLY)) { + /* + * If the frontend is opened in read-only mode, only the ioctls + * that don't interfere with the tune logic should be accepted. + * That allows an external application to monitor the DVB QoS and + * statistics parameters. + * + * That matches all _IOR() ioctls, except for two special cases: + * - FE_GET_EVENT is part of the tuning logic on a DVB application; + * - FE_DISEQC_RECV_SLAVE_REPLY is part of DiSEqC 2.0 + * setup + * So, those two ioctls should also return -EPERM, as otherwise + * reading from them would interfere with a DVB tune application + */ + if ((file->f_flags & O_ACCMODE) == O_RDONLY + && (_IOC_DIR(cmd) != _IOC_READ + || cmd == FE_GET_EVENT + || cmd == FE_DISEQC_RECV_SLAVE_REPLY)) { up(&fepriv->sem); return -EPERM; } - if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) - err = dvb_frontend_ioctl_properties(file, cmd, parg); - else { - c->state = DTV_UNDEFINED; - err = dvb_frontend_ioctl_legacy(file, cmd, parg); - } + err = dvb_frontend_handle_ioctl(file, cmd, parg); up(&fepriv->sem); return err; } -static int dvb_frontend_ioctl_properties(struct file *file, - unsigned int cmd, void *parg) -{ - struct dvb_device *dvbdev = file->private_data; - struct dvb_frontend *fe = dvbdev->priv; - struct dvb_frontend_private *fepriv = fe->frontend_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int err = 0; - - struct dtv_properties *tvps = parg; - struct dtv_property *tvp = NULL; - int i; - - dev_dbg(fe->dvb->device, "%s:\n", __func__); - - if (cmd == FE_SET_PROPERTY) { - dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); - dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); - - /* Put an arbitrary limit on the number of messages that can - * be sent at once */ - if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) - return -EINVAL; - - tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp)); - if (IS_ERR(tvp)) - return PTR_ERR(tvp); - - for (i = 0; i < tvps->num; i++) { - err = dtv_property_process_set(fe, tvp + i, file); - if (err < 0) - goto out; - (tvp + i)->result = err; - } - - if (c->state == DTV_TUNE) - dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__); - - } else if (cmd == FE_GET_PROPERTY) { - struct dtv_frontend_properties getp = fe->dtv_property_cache; - - dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); - dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); - - /* Put an arbitrary limit on the number of messages that can - * be sent at once */ - if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) - return -EINVAL; - - tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp)); - if (IS_ERR(tvp)) - return PTR_ERR(tvp); - - /* - * Let's use our own copy of property cache, in order to - * avoid mangling with DTV zigzag logic, as drivers might - * return crap, if they don't check if the data is available - * before updating the properties cache. - */ - if (fepriv->state != FESTATE_IDLE) { - err = dtv_get_frontend(fe, &getp, NULL); - if (err < 0) - goto out; - } - for (i = 0; i < tvps->num; i++) { - err = dtv_property_process_get(fe, &getp, tvp + i, file); - if (err < 0) - goto out; - (tvp + i)->result = err; - } - - if (copy_to_user((void __user *)tvps->props, tvp, - tvps->num * sizeof(struct dtv_property))) { - err = -EFAULT; - goto out; - } - - } else - err = -EOPNOTSUPP; - -out: - kfree(tvp); - return err; -} - static int dtv_set_frontend(struct dvb_frontend *fe) { struct dvb_frontend_private *fepriv = fe->frontend_priv; @@ -2200,16 +2103,102 @@ static int dtv_set_frontend(struct dvb_frontend *fe) } -static int dvb_frontend_ioctl_legacy(struct file *file, - unsigned int cmd, void *parg) +static int dvb_frontend_handle_ioctl(struct file *file, + unsigned int cmd, void *parg) { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int err = -EOPNOTSUPP; + int i, err; + + dev_dbg(fe->dvb->device, "%s:\n", __func__); switch (cmd) { + case FE_SET_PROPERTY: { + struct dtv_properties *tvps = parg; + struct dtv_property *tvp = NULL; + + dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", + __func__, tvps->num); + dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", + __func__, tvps->props); + + /* + * Put an arbitrary limit on the number of messages that can + * be sent at once + */ + if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS)) + return -EINVAL; + + tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp)); + if (IS_ERR(tvp)) + return PTR_ERR(tvp); + + for (i = 0; i < tvps->num; i++) { + err = dtv_property_process_set(fe, file, + (tvp + i)->cmd, + (tvp + i)->u.data); + if (err < 0) { + kfree(tvp); + return err; + } + } + kfree(tvp); + break; + } + case FE_GET_PROPERTY: { + struct dtv_properties *tvps = parg; + struct dtv_property *tvp = NULL; + struct dtv_frontend_properties getp = fe->dtv_property_cache; + + dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", + __func__, tvps->num); + dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", + __func__, tvps->props); + + /* + * Put an arbitrary limit on the number of messages that can + * be sent at once + */ + if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS)) + return -EINVAL; + + tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp)); + if (IS_ERR(tvp)) + return PTR_ERR(tvp); + + /* + * Let's use our own copy of property cache, in order to + * avoid mangling with DTV zigzag logic, as drivers might + * return crap, if they don't check if the data is available + * before updating the properties cache. + */ + if (fepriv->state != FESTATE_IDLE) { + err = dtv_get_frontend(fe, &getp, NULL); + if (err < 0) { + kfree(tvp); + return err; + } + } + for (i = 0; i < tvps->num; i++) { + err = dtv_property_process_get(fe, &getp, + tvp + i, file); + if (err < 0) { + kfree(tvp); + return err; + } + } + + if (copy_to_user((void __user *)tvps->props, tvp, + tvps->num * sizeof(struct dtv_property))) { + kfree(tvp); + return -EFAULT; + } + kfree(tvp); + break; + } + case FE_GET_INFO: { struct dvb_frontend_info* info = parg; @@ -2273,42 +2262,6 @@ static int dvb_frontend_ioctl_legacy(struct file *file, break; } - case FE_READ_BER: - if (fe->ops.read_ber) { - if (fepriv->thread) - err = fe->ops.read_ber(fe, (__u32 *) parg); - else - err = -EAGAIN; - } - break; - - case FE_READ_SIGNAL_STRENGTH: - if (fe->ops.read_signal_strength) { - if (fepriv->thread) - err = fe->ops.read_signal_strength(fe, (__u16 *) parg); - else - err = -EAGAIN; - } - break; - - case FE_READ_SNR: - if (fe->ops.read_snr) { - if (fepriv->thread) - err = fe->ops.read_snr(fe, (__u16 *) parg); - else - err = -EAGAIN; - } - break; - - case FE_READ_UNCORRECTED_BLOCKS: - if (fe->ops.read_ucblocks) { - if (fepriv->thread) - err = fe->ops.read_ucblocks(fe, (__u32 *) parg); - else - err = -EAGAIN; - } - break; - case FE_DISEQC_RESET_OVERLOAD: if (fe->ops.diseqc_reset_overload) { err = fe->ops.diseqc_reset_overload(fe); @@ -2360,6 +2313,23 @@ static int dvb_frontend_ioctl_legacy(struct file *file, } break; + case FE_DISEQC_RECV_SLAVE_REPLY: + if (fe->ops.diseqc_recv_slave_reply) + err = fe->ops.diseqc_recv_slave_reply(fe, parg); + break; + + case FE_ENABLE_HIGH_LNB_VOLTAGE: + if (fe->ops.enable_high_lnb_voltage) + err = fe->ops.enable_high_lnb_voltage(fe, (long) parg); + break; + + case FE_SET_FRONTEND_TUNE_MODE: + fepriv->tune_mode_flags = (unsigned long) parg; + err = 0; + break; + + /* DEPRECATED dish control ioctls */ + case FE_DISHNETWORK_SEND_LEGACY_CMD: if (fe->ops.dishnetwork_send_legacy_command) { err = fe->ops.dishnetwork_send_legacy_command(fe, @@ -2425,16 +2395,46 @@ static int dvb_frontend_ioctl_legacy(struct file *file, } break; - case FE_DISEQC_RECV_SLAVE_REPLY: - if (fe->ops.diseqc_recv_slave_reply) - err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg); + /* DEPRECATED statistics ioctls */ + + case FE_READ_BER: + if (fe->ops.read_ber) { + if (fepriv->thread) + err = fe->ops.read_ber(fe, parg); + else + err = -EAGAIN; + } break; - case FE_ENABLE_HIGH_LNB_VOLTAGE: - if (fe->ops.enable_high_lnb_voltage) - err = fe->ops.enable_high_lnb_voltage(fe, (long) parg); + case FE_READ_SIGNAL_STRENGTH: + if (fe->ops.read_signal_strength) { + if (fepriv->thread) + err = fe->ops.read_signal_strength(fe, parg); + else + err = -EAGAIN; + } break; + case FE_READ_SNR: + if (fe->ops.read_snr) { + if (fepriv->thread) + err = fe->ops.read_snr(fe, parg); + else + err = -EAGAIN; + } + break; + + case FE_READ_UNCORRECTED_BLOCKS: + if (fe->ops.read_ucblocks) { + if (fepriv->thread) + err = fe->ops.read_ucblocks(fe, parg); + else + err = -EAGAIN; + } + break; + + /* DEPRECATED DVBv3 ioctls */ + case FE_SET_FRONTEND: err = dvbv3_set_delivery_system(fe); if (err) @@ -2461,11 +2461,10 @@ static int dvb_frontend_ioctl_legacy(struct file *file, err = dtv_get_frontend(fe, &getp, parg); break; } - case FE_SET_FRONTEND_TUNE_MODE: - fepriv->tune_mode_flags = (unsigned long) parg; - err = 0; - break; - } + + default: + return -ENOTSUPP; + } /* switch */ return err; } diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h index 907a05bde162..ace0c2fb26c2 100644 --- a/drivers/media/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb-core/dvb_frontend.h @@ -180,8 +180,8 @@ enum dvbfe_search { /** * struct dvb_tuner_ops - Tuner information and callbacks * - * @info: embedded struct dvb_tuner_info with tuner properties - * @release: callback function called when frontend is dettached. + * @info: embedded &struct dvb_tuner_info with tuner properties + * @release: callback function called when frontend is detached. * drivers should free any allocated memory. * @init: callback function used to initialize the tuner device. * @sleep: callback function used to put the tuner to sleep. @@ -191,14 +191,14 @@ enum dvbfe_search { * resuming from suspend. * @set_params: callback function used to inform the tuner to tune * into a digital TV channel. The properties to be used - * are stored at @dvb_frontend.dtv_property_cache;. The - * tuner demod can change the parameters to reflect the - * changes needed for the channel to be tuned, and + * are stored at &struct dvb_frontend.dtv_property_cache. + * The tuner demod can change the parameters to reflect + * the changes needed for the channel to be tuned, and * update statistics. This is the recommended way to set * the tuner parameters and should be used on newer * drivers. * @set_analog_params: callback function used to tune into an analog TV - * channel on hybrid tuners. It passes @analog_parameters; + * channel on hybrid tuners. It passes @analog_parameters * to the driver. * @set_config: callback function used to send some tuner-specific * parameters. @@ -207,9 +207,9 @@ enum dvbfe_search { * @get_if_frequency: get the Intermediate Frequency, in Hz. For baseband, * should return 0. * @get_status: returns the frontend lock status - * @get_rf_strength: returns the RF signal strengh. Used mostly to support + * @get_rf_strength: returns the RF signal strength. Used mostly to support * analog TV and radio. Digital TV should report, instead, - * via DVBv5 API (@dvb_frontend.dtv_property_cache;). + * via DVBv5 API (&struct dvb_frontend.dtv_property_cache). * @get_afc: Used only by analog TV core. Reports the frequency * drift due to AFC. * @calc_regs: callback function used to pass register data settings @@ -217,7 +217,7 @@ enum dvbfe_search { * @set_frequency: Set a new frequency. Shouldn't be used on newer drivers. * @set_bandwidth: Set a new frequency. Shouldn't be used on newer drivers. * - * NOTE: frequencies used on get_frequency and set_frequency are in Hz for + * NOTE: frequencies used on @get_frequency and @set_frequency are in Hz for * terrestrial/cable or kHz for satellite. * */ @@ -283,14 +283,14 @@ struct analog_demod_info { * @set_params: callback function used to inform the demod to set the * demodulator parameters needed to decode an analog or * radio channel. The properties are passed via - * struct @analog_params;. + * &struct analog_params. * @has_signal: returns 0xffff if has signal, or 0 if it doesn't. * @get_afc: Used only by analog TV core. Reports the frequency * drift due to AFC. * @tuner_status: callback function that returns tuner status bits, e. g. - * TUNER_STATUS_LOCKED and TUNER_STATUS_STEREO. + * %TUNER_STATUS_LOCKED and %TUNER_STATUS_STEREO. * @standby: set the tuner to standby mode. - * @release: callback function called when frontend is dettached. + * @release: callback function called when frontend is detached. * drivers should free any allocated memory. * @i2c_gate_ctrl: controls the I2C gate. Newer drivers should use I2C * mux support instead. @@ -321,10 +321,10 @@ struct dtv_frontend_properties; * struct dvb_frontend_ops - Demodulation information and callbacks for * ditialt TV * - * @info: embedded struct dvb_tuner_info with tuner properties + * @info: embedded &struct dvb_tuner_info with tuner properties * @delsys: Delivery systems supported by the frontend * @detach: callback function called when frontend is detached. - * drivers should clean up, but not yet free the struct + * drivers should clean up, but not yet free the &struct * dvb_frontend allocation. * @release: callback function called when frontend is ready to be * freed. @@ -338,57 +338,57 @@ struct dtv_frontend_properties; * allow other drivers to write data into their registers. * Should not be used on new drivers. * @tune: callback function used by demod drivers that use - * @DVBFE_ALGO_HW; to tune into a frequency. + * @DVBFE_ALGO_HW to tune into a frequency. * @get_frontend_algo: returns the desired hardware algorithm. * @set_frontend: callback function used to inform the demod to set the * parameters for demodulating a digital TV channel. - * The properties to be used are stored at - * @dvb_frontend.dtv_property_cache;. The demod can change + * The properties to be used are stored at &struct + * dvb_frontend.dtv_property_cache. The demod can change * the parameters to reflect the changes needed for the * channel to be decoded, and update statistics. * @get_tune_settings: callback function * @get_frontend: callback function used to inform the parameters * actuall in use. The properties to be used are stored at - * @dvb_frontend.dtv_property_cache; and update + * &struct dvb_frontend.dtv_property_cache and update * statistics. Please notice that it should not return * an error code if the statistics are not available * because the demog is not locked. * @read_status: returns the locking status of the frontend. * @read_ber: legacy callback function to return the bit error rate. * Newer drivers should provide such info via DVBv5 API, - * e. g. @set_frontend;/@get_frontend;, implementing this + * e. g. @set_frontend;/@get_frontend, implementing this * callback only if DVBv3 API compatibility is wanted. * @read_signal_strength: legacy callback function to return the signal * strength. Newer drivers should provide such info via - * DVBv5 API, e. g. @set_frontend;/@get_frontend;, + * DVBv5 API, e. g. @set_frontend/@get_frontend, * implementing this callback only if DVBv3 API * compatibility is wanted. * @read_snr: legacy callback function to return the Signal/Noise * rate. Newer drivers should provide such info via - * DVBv5 API, e. g. @set_frontend;/@get_frontend;, + * DVBv5 API, e. g. @set_frontend/@get_frontend, * implementing this callback only if DVBv3 API * compatibility is wanted. * @read_ucblocks: legacy callback function to return the Uncorrected Error * Blocks. Newer drivers should provide such info via - * DVBv5 API, e. g. @set_frontend;/@get_frontend;, + * DVBv5 API, e. g. @set_frontend/@get_frontend, * implementing this callback only if DVBv3 API * compatibility is wanted. * @diseqc_reset_overload: callback function to implement the - * FE_DISEQC_RESET_OVERLOAD ioctl (only Satellite) + * FE_DISEQC_RESET_OVERLOAD() ioctl (only Satellite) * @diseqc_send_master_cmd: callback function to implement the - * FE_DISEQC_SEND_MASTER_CMD ioctl (only Satellite). + * FE_DISEQC_SEND_MASTER_CMD() ioctl (only Satellite). * @diseqc_recv_slave_reply: callback function to implement the - * FE_DISEQC_RECV_SLAVE_REPLY ioctl (only Satellite) + * FE_DISEQC_RECV_SLAVE_REPLY() ioctl (only Satellite) * @diseqc_send_burst: callback function to implement the - * FE_DISEQC_SEND_BURST ioctl (only Satellite). + * FE_DISEQC_SEND_BURST() ioctl (only Satellite). * @set_tone: callback function to implement the - * FE_SET_TONE ioctl (only Satellite). + * FE_SET_TONE() ioctl (only Satellite). * @set_voltage: callback function to implement the - * FE_SET_VOLTAGE ioctl (only Satellite). + * FE_SET_VOLTAGE() ioctl (only Satellite). * @enable_high_lnb_voltage: callback function to implement the - * FE_ENABLE_HIGH_LNB_VOLTAGE ioctl (only Satellite). + * FE_ENABLE_HIGH_LNB_VOLTAGE() ioctl (only Satellite). * @dishnetwork_send_legacy_command: callback function to implement the - * FE_DISHNETWORK_SEND_LEGACY_CMD ioctl (only Satellite). + * FE_DISHNETWORK_SEND_LEGACY_CMD() ioctl (only Satellite). * Drivers should not use this, except when the DVB * core emulation fails to provide proper support (e.g. * if @set_voltage takes more than 8ms to work), and @@ -399,15 +399,10 @@ struct dtv_frontend_properties; * @ts_bus_ctrl: callback function used to take control of the TS bus. * @set_lna: callback function to power on/off/auto the LNA. * @search: callback function used on some custom algo search algos. - * @tuner_ops: pointer to struct dvb_tuner_ops - * @analog_ops: pointer to struct analog_demod_ops - * @set_property: callback function to allow the frontend to validade - * incoming properties. Should not be used on new drivers. - * @get_property: callback function to allow the frontend to override - * outcoming properties. Should not be used on new drivers. + * @tuner_ops: pointer to &struct dvb_tuner_ops + * @analog_ops: pointer to &struct analog_demod_ops */ struct dvb_frontend_ops { - struct dvb_frontend_info info; u8 delsys[MAX_DELSYS]; @@ -466,9 +461,6 @@ struct dvb_frontend_ops { struct dvb_tuner_ops tuner_ops; struct analog_demod_ops analog_ops; - - int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); - int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); }; #ifdef __DVB_CORE__ @@ -565,15 +557,15 @@ struct dtv_frontend_properties { enum fe_sec_voltage voltage; enum fe_sec_tone_mode sectone; - enum fe_spectral_inversion inversion; - enum fe_code_rate fec_inner; + enum fe_spectral_inversion inversion; + enum fe_code_rate fec_inner; enum fe_transmit_mode transmission_mode; u32 bandwidth_hz; /* 0 = AUTO */ enum fe_guard_interval guard_interval; - enum fe_hierarchy hierarchy; + enum fe_hierarchy hierarchy; u32 symbol_rate; - enum fe_code_rate code_rate_HP; - enum fe_code_rate code_rate_LP; + enum fe_code_rate code_rate_HP; + enum fe_code_rate code_rate_LP; enum fe_pilot pilot; enum fe_rolloff rolloff; @@ -628,11 +620,6 @@ struct dtv_frontend_properties { struct dtv_fe_stats post_bit_count; struct dtv_fe_stats block_error; struct dtv_fe_stats block_count; - - /* private: */ - /* Cache State */ - u32 state; - }; #define DVB_FE_NO_EXIT 0 @@ -643,16 +630,16 @@ struct dtv_frontend_properties { /** * struct dvb_frontend - Frontend structure to be used on drivers. * - * @refcount: refcount to keep track of struct dvb_frontend + * @refcount: refcount to keep track of &struct dvb_frontend * references - * @ops: embedded struct dvb_frontend_ops - * @dvb: pointer to struct dvb_adapter + * @ops: embedded &struct dvb_frontend_ops + * @dvb: pointer to &struct dvb_adapter * @demodulator_priv: demod private data * @tuner_priv: tuner private data * @frontend_priv: frontend private data * @sec_priv: SEC private data * @analog_demod_priv: Analog demod private data - * @dtv_property_cache: embedded struct dtv_frontend_properties + * @dtv_property_cache: embedded &struct dtv_frontend_properties * @callback: callback function used on some drivers to call * either the tuner or the demodulator. * @id: Frontend ID @@ -681,8 +668,8 @@ struct dvb_frontend { /** * dvb_register_frontend() - Registers a DVB frontend at the adapter * - * @dvb: pointer to the dvb adapter - * @fe: pointer to the frontend struct + * @dvb: pointer to &struct dvb_adapter + * @fe: pointer to &struct dvb_frontend * * Allocate and initialize the private data needed by the frontend core to * manage the frontend and calls dvb_register_device() to register a new @@ -695,7 +682,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb, /** * dvb_unregister_frontend() - Unregisters a DVB frontend * - * @fe: pointer to the frontend struct + * @fe: pointer to &struct dvb_frontend * * Stops the frontend kthread, calls dvb_unregister_device() and frees the * private frontend data allocated by dvb_register_frontend(). @@ -709,14 +696,14 @@ int dvb_unregister_frontend(struct dvb_frontend *fe); /** * dvb_frontend_detach() - Detaches and frees frontend specific data * - * @fe: pointer to the frontend struct + * @fe: pointer to &struct dvb_frontend * * This function should be called after dvb_unregister_frontend(). It * calls the SEC, tuner and demod release functions: * &dvb_frontend_ops.release_sec, &dvb_frontend_ops.tuner_ops.release, * &dvb_frontend_ops.analog_ops.release and &dvb_frontend_ops.release. * - * If the driver is compiled with CONFIG_MEDIA_ATTACH, it also decreases + * If the driver is compiled with %CONFIG_MEDIA_ATTACH, it also decreases * the module reference count, needed to allow userspace to remove the * previously used DVB frontend modules. */ @@ -725,7 +712,7 @@ void dvb_frontend_detach(struct dvb_frontend *fe); /** * dvb_frontend_suspend() - Suspends a Digital TV frontend * - * @fe: pointer to the frontend struct + * @fe: pointer to &struct dvb_frontend * * This function prepares a Digital TV frontend to suspend. * @@ -743,7 +730,7 @@ int dvb_frontend_suspend(struct dvb_frontend *fe); /** * dvb_frontend_resume() - Resumes a Digital TV frontend * - * @fe: pointer to the frontend struct + * @fe: pointer to &struct dvb_frontend * * This function resumes the usual operation of the tuner after resume. * @@ -764,7 +751,7 @@ int dvb_frontend_resume(struct dvb_frontend *fe); /** * dvb_frontend_reinitialise() - forces a reinitialisation at the frontend * - * @fe: pointer to the frontend struct + * @fe: pointer to &struct dvb_frontend * * Calls &dvb_frontend_ops.init\(\) and &dvb_frontend_ops.tuner_ops.init\(\), * and resets SEC tone and voltage (for Satellite systems). @@ -779,16 +766,16 @@ void dvb_frontend_reinitialise(struct dvb_frontend *fe); * dvb_frontend_sleep_until() - Sleep for the amount of time given by * add_usec parameter * - * @waketime: pointer to a struct ktime_t + * @waketime: pointer to &struct ktime_t * @add_usec: time to sleep, in microseconds * * This function is used to measure the time required for the - * %FE_DISHNETWORK_SEND_LEGACY_CMD ioctl to work. It needs to be as precise + * FE_DISHNETWORK_SEND_LEGACY_CMD() ioctl to work. It needs to be as precise * as possible, as it affects the detection of the dish tone command at the * satellite subsystem. * * Its used internally by the DVB frontend core, in order to emulate - * %FE_DISHNETWORK_SEND_LEGACY_CMD using the &dvb_frontend_ops.set_voltage\(\) + * FE_DISHNETWORK_SEND_LEGACY_CMD() using the &dvb_frontend_ops.set_voltage\(\) * callback. * * NOTE: it should not be used at the drivers, as the emulation for the diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index 06b0dcc13695..c018e3c06d5d 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c @@ -125,7 +125,7 @@ struct dvb_net_priv { }; -/** +/* * Determine the packet's protocol ID. The rule here is that we * assume 802.3 if the type field is short enough to be a length. * This is normal practice and works for any 'now in use' protocol. @@ -155,7 +155,7 @@ static __be16 dvb_net_eth_type_trans(struct sk_buff *skb, rawp = skb->data; - /** + /* * This is a magic hack to spot IPX packets. Older Novell breaks * the protocol design and runs IPX over 802.3 without an 802.2 LLC * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This @@ -164,7 +164,7 @@ static __be16 dvb_net_eth_type_trans(struct sk_buff *skb, if (*(unsigned short *)rawp == 0xFFFF) return htons(ETH_P_802_3); - /** + /* * Real 802.2 LLC */ return htons(ETH_P_802_2); @@ -215,7 +215,8 @@ static int ule_exthdr_padding(struct dvb_net_priv *p) return 0; } -/** Handle ULE extension headers. +/* + * Handle ULE extension headers. * Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding. * Returns: >= 0: nr. of bytes consumed by next extension header * -1: Mandatory extension header that is not recognized or TEST SNDU; discard. @@ -291,7 +292,7 @@ static int handle_ule_extensions( struct dvb_net_priv *p ) } -/** Prepare for a new ULE SNDU: reset the decoder state. */ +/* Prepare for a new ULE SNDU: reset the decoder state. */ static inline void reset_ule( struct dvb_net_priv *p ) { p->ule_skb = NULL; @@ -304,7 +305,7 @@ static inline void reset_ule( struct dvb_net_priv *p ) p->ule_bridged = 0; } -/** +/* * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of * TS cells of a single PID. */ @@ -1005,7 +1006,7 @@ static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len, { struct net_device *dev = filter->priv; - /** + /* * we rely on the DVB API definition where exactly one complete * section is delivered in buffer1 */ diff --git a/drivers/media/dvb-core/dvb_net.h b/drivers/media/dvb-core/dvb_net.h index e9b18aa03e02..1eae8bad7cc1 100644 --- a/drivers/media/dvb-core/dvb_net.h +++ b/drivers/media/dvb-core/dvb_net.h @@ -30,6 +30,22 @@ #ifdef CONFIG_DVB_NET +/** + * struct dvb_net - describes a DVB network interface + * + * @dvbdev: pointer to &struct dvb_device. + * @device: array of pointers to &struct net_device. + * @state: array of integers to each net device. A value + * different than zero means that the interface is + * in usage. + * @exit: flag to indicate when the device is being removed. + * @demux: pointer to &struct dmx_demux. + * @ioctl_mutex: protect access to this struct. + * + * Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network + * devices. + */ + struct dvb_net { struct dvb_device *dvbdev; struct net_device *device[DVB_NET_DEVICES_MAX]; @@ -39,8 +55,22 @@ struct dvb_net { struct mutex ioctl_mutex; }; -void dvb_net_release(struct dvb_net *); -int dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *); +/** + * dvb_net_init - nitializes a digital TV network device and registers it. + * + * @adap: pointer to &struct dvb_adapter. + * @dvbnet: pointer to &struct dvb_net. + * @dmxdemux: pointer to &struct dmx_demux. + */ +int dvb_net_init(struct dvb_adapter *adap, struct dvb_net *dvbnet, + struct dmx_demux *dmxdemux); + +/** + * dvb_net_release - releases a digital TV network device and unregisters it. + * + * @dvbnet: pointer to &struct dvb_net. + */ +void dvb_net_release(struct dvb_net *dvbnet); #else diff --git a/drivers/media/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb-core/dvb_ringbuffer.c index 2322af1b8742..53011629c9ad 100644 --- a/drivers/media/dvb-core/dvb_ringbuffer.c +++ b/drivers/media/dvb-core/dvb_ringbuffer.c @@ -66,12 +66,12 @@ ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf) { ssize_t free; - /* ACCESS_ONCE() to load read pointer on writer side + /* READ_ONCE() to load read pointer on writer side * this pairs with smp_store_release() in dvb_ringbuffer_read(), * dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(), * or dvb_ringbuffer_reset() */ - free = ACCESS_ONCE(rbuf->pread) - rbuf->pwrite; + free = READ_ONCE(rbuf->pread) - rbuf->pwrite; if (free <= 0) free += rbuf->size; return free-1; @@ -143,7 +143,7 @@ ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, si todo -= split; /* smp_store_release() for read pointer update to ensure * that buf is not overwritten until read is complete, - * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free() + * this pairs with READ_ONCE() in dvb_ringbuffer_free() */ smp_store_release(&rbuf->pread, 0); } @@ -168,7 +168,7 @@ void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len) todo -= split; /* smp_store_release() for read pointer update to ensure * that buf is not overwritten until read is complete, - * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free() + * this pairs with READ_ONCE() in dvb_ringbuffer_free() */ smp_store_release(&rbuf->pread, 0); } diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 41aad0f99d73..060c60ddfcc3 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -51,8 +51,15 @@ static LIST_HEAD(dvb_adapter_list); static DEFINE_MUTEX(dvbdev_register_lock); static const char * const dnames[] = { - "video", "audio", "sec", "frontend", "demux", "dvr", "ca", - "net", "osd" + [DVB_DEVICE_VIDEO] = "video", + [DVB_DEVICE_AUDIO] = "audio", + [DVB_DEVICE_SEC] = "sec", + [DVB_DEVICE_FRONTEND] = "frontend", + [DVB_DEVICE_DEMUX] = "demux", + [DVB_DEVICE_DVR] = "dvr", + [DVB_DEVICE_CA] = "ca", + [DVB_DEVICE_NET] = "net", + [DVB_DEVICE_OSD] = "osd" }; #ifdef CONFIG_DVB_DYNAMIC_MINORS @@ -60,7 +67,22 @@ static const char * const dnames[] = { #define DVB_MAX_IDS MAX_DVB_MINORS #else #define DVB_MAX_IDS 4 -#define nums2minor(num, type, id) ((num << 6) | (id << 4) | type) + +static const u8 minor_type[] = { + [DVB_DEVICE_VIDEO] = 0, + [DVB_DEVICE_AUDIO] = 1, + [DVB_DEVICE_SEC] = 2, + [DVB_DEVICE_FRONTEND] = 3, + [DVB_DEVICE_DEMUX] = 4, + [DVB_DEVICE_DVR] = 5, + [DVB_DEVICE_CA] = 6, + [DVB_DEVICE_NET] = 7, + [DVB_DEVICE_OSD] = 8, +}; + +#define nums2minor(num, type, id) \ + (((num) << 6) | ((id) << 4) | minor_type[type]) + #define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) #endif @@ -426,8 +448,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev, } int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, - const struct dvb_device *template, void *priv, int type, - int demux_sink_pads) + const struct dvb_device *template, void *priv, + enum dvb_device_type type, int demux_sink_pads) { struct dvb_device *dvbdev; struct file_operations *dvbdevfops; diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h index 49189392cf3b..bbc1c20c0529 100644 --- a/drivers/media/dvb-core/dvbdev.h +++ b/drivers/media/dvb-core/dvbdev.h @@ -35,15 +35,37 @@ #define DVB_UNSET (-1) -#define DVB_DEVICE_VIDEO 0 -#define DVB_DEVICE_AUDIO 1 -#define DVB_DEVICE_SEC 2 -#define DVB_DEVICE_FRONTEND 3 -#define DVB_DEVICE_DEMUX 4 -#define DVB_DEVICE_DVR 5 -#define DVB_DEVICE_CA 6 -#define DVB_DEVICE_NET 7 -#define DVB_DEVICE_OSD 8 +/* List of DVB device types */ + +/** + * enum dvb_device_type - type of the Digital TV device + * + * @DVB_DEVICE_SEC: Digital TV standalone Common Interface (CI) + * @DVB_DEVICE_FRONTEND: Digital TV frontend. + * @DVB_DEVICE_DEMUX: Digital TV demux. + * @DVB_DEVICE_DVR: Digital TV digital video record (DVR). + * @DVB_DEVICE_CA: Digital TV Conditional Access (CA). + * @DVB_DEVICE_NET: Digital TV network. + * + * @DVB_DEVICE_VIDEO: Digital TV video decoder. + * Deprecated. Used only on av7110-av. + * @DVB_DEVICE_AUDIO: Digital TV audio decoder. + * Deprecated. Used only on av7110-av. + * @DVB_DEVICE_OSD: Digital TV On Screen Display (OSD). + * Deprecated. Used only on av7110. + */ +enum dvb_device_type { + DVB_DEVICE_SEC, + DVB_DEVICE_FRONTEND, + DVB_DEVICE_DEMUX, + DVB_DEVICE_DVR, + DVB_DEVICE_CA, + DVB_DEVICE_NET, + + DVB_DEVICE_VIDEO, + DVB_DEVICE_AUDIO, + DVB_DEVICE_OSD, +}; #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ static short adapter_nr[] = \ @@ -104,8 +126,7 @@ struct dvb_adapter { * @list_head: List head with all DVB devices * @fops: pointer to struct file_operations * @adapter: pointer to the adapter that holds this device node - * @type: type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND, - * DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET + * @type: type of the device, as defined by &enum dvb_device_type. * @minor: devnode minor number. Major number is always DVB_MAJOR. * @id: device ID number, inside the adapter * @readers: Initialized by the caller. Each call to open() in Read Only mode @@ -135,7 +156,7 @@ struct dvb_device { struct list_head list_head; const struct file_operations *fops; struct dvb_adapter *adapter; - int type; + enum dvb_device_type type; int minor; u32 id; @@ -194,9 +215,7 @@ int dvb_unregister_adapter(struct dvb_adapter *adap); * stored * @template: Template used to create &pdvbdev; * @priv: private data - * @type: type of the device: %DVB_DEVICE_SEC, %DVB_DEVICE_FRONTEND, - * %DVB_DEVICE_DEMUX, %DVB_DEVICE_DVR, %DVB_DEVICE_CA, - * %DVB_DEVICE_NET + * @type: type of the device, as defined by &enum dvb_device_type. * @demux_sink_pads: Number of demux outputs, to be used to create the TS * outputs via the Media Controller. */ @@ -204,7 +223,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, const struct dvb_device *template, void *priv, - int type, + enum dvb_device_type type, int demux_sink_pads); /** @@ -242,7 +261,7 @@ void dvb_unregister_device(struct dvb_device *dvbdev); * dvb_create_media_graph - Creates media graph for the Digital TV part of the * device. * - * @adap: pointer to struct dvb_adapter + * @adap: pointer to &struct dvb_adapter * @create_rf_connector: if true, it creates the RF connector too * * This function checks all DVB-related functions at the media controller @@ -255,12 +274,23 @@ void dvb_unregister_device(struct dvb_device *dvbdev); __must_check int dvb_create_media_graph(struct dvb_adapter *adap, bool create_rf_connector); +/** + * dvb_register_media_controller - registers a media controller at DVB adapter + * + * @adap: pointer to &struct dvb_adapter + * @mdev: pointer to &struct media_device + */ static inline void dvb_register_media_controller(struct dvb_adapter *adap, struct media_device *mdev) { adap->mdev = mdev; } +/** + * dvb_get_media_controller - gets the associated media controller + * + * @adap: pointer to &struct dvb_adapter + */ static inline struct media_device *dvb_get_media_controller(struct dvb_adapter *adap) { @@ -277,20 +307,71 @@ int dvb_create_media_graph(struct dvb_adapter *adap, #define dvb_get_media_controller(a) NULL #endif -int dvb_generic_open (struct inode *inode, struct file *file); -int dvb_generic_release (struct inode *inode, struct file *file); -long dvb_generic_ioctl (struct file *file, - unsigned int cmd, unsigned long arg); +/** + * dvb_generic_open - Digital TV open function, used by DVB devices + * + * @inode: pointer to &struct inode. + * @file: pointer to &struct file. + * + * Checks if a DVB devnode is still valid, and if the permissions are + * OK and increment negative use count. + */ +int dvb_generic_open(struct inode *inode, struct file *file); -/* we don't mess with video_usercopy() any more, -we simply define out own dvb_usercopy(), which will hopefully become -generic_usercopy() someday... */ +/** + * dvb_generic_close - Digital TV close function, used by DVB devices + * + * @inode: pointer to &struct inode. + * @file: pointer to &struct file. + * + * Checks if a DVB devnode is still valid, and if the permissions are + * OK and decrement negative use count. + */ +int dvb_generic_release(struct inode *inode, struct file *file); +/** + * dvb_generic_ioctl - Digital TV close function, used by DVB devices + * + * @file: pointer to &struct file. + * @cmd: Ioctl name. + * @arg: Ioctl argument. + * + * Checks if a DVB devnode and struct dvbdev.kernel_ioctl is still valid. + * If so, calls dvb_usercopy(). + */ +long dvb_generic_ioctl(struct file *file, + unsigned int cmd, unsigned long arg); + +/** + * dvb_usercopy - copies data from/to userspace memory when an ioctl is + * issued. + * + * @file: Pointer to struct &file. + * @cmd: Ioctl name. + * @arg: Ioctl argument. + * @func: function that will actually handle the ioctl + * + * Ancillary function that uses ioctl direction and size to copy from + * userspace. Then, it calls @func, and, if needed, data is copied back + * to userspace. + */ int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, int (*func)(struct file *file, unsigned int cmd, void *arg)); /** generic DVB attach function. */ #ifdef CONFIG_MEDIA_ATTACH + +/** + * dvb_attach - attaches a DVB frontend into the DVB core. + * + * @FUNCTION: function on a frontend module to be called. + * @ARGS...: @FUNCTION arguments. + * + * This ancillary function loads a frontend module in runtime and runs + * the @FUNCTION function there, with @ARGS. + * As it increments symbol usage cont, at unregister, dvb_detach() + * should be called. + */ #define dvb_attach(FUNCTION, ARGS...) ({ \ void *__r = NULL; \ typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ @@ -304,6 +385,14 @@ int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, __r; \ }) +/** + * dvb_detach - detaches a DVB frontend loaded via dvb_attach() + * + * @FUNC: attach function + * + * Decrements usage count for a function previously called via dvb_attach(). + */ + #define dvb_detach(FUNC) symbol_put_addr(FUNC) #else diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index 2631d0e0a024..d17722eb4456 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -173,7 +173,7 @@ config DVB_STB6000 tristate "ST STB6000 silicon tuner" depends on DVB_CORE && I2C default m if !MEDIA_SUBDRV_AUTOSELECT - help + help A DVB-S silicon tuner module. Say Y when you want to support this tuner. config DVB_STV0299 @@ -187,7 +187,7 @@ config DVB_STV6110 tristate "ST STV6110 silicon tuner" depends on DVB_CORE && I2C default m if !MEDIA_SUBDRV_AUTOSELECT - help + help A DVB-S silicon tuner module. Say Y when you want to support this tuner. config DVB_STV0900 @@ -902,7 +902,7 @@ config DVB_HELENE depends on DVB_CORE && I2C default m if !MEDIA_SUBDRV_AUTOSELECT help - Say Y when you want to support this frontend. + Say Y when you want to support this frontend. comment "Tools to develop new frontends" diff --git a/drivers/media/dvb-frontends/af9013.h b/drivers/media/dvb-frontends/af9013.h index 353274524f1b..a290722c04fd 100644 --- a/drivers/media/dvb-frontends/af9013.h +++ b/drivers/media/dvb-frontends/af9013.h @@ -38,6 +38,13 @@ * @api_version: Firmware API version. * @gpio: GPIOs. * @get_dvb_frontend: Get DVB frontend callback. + * + * AF9013/5 GPIOs (mostly guessed): + * * demod#1-gpio#0 - set demod#2 i2c-addr for dual devices + * * demod#1-gpio#1 - xtal setting (?) + * * demod#1-gpio#3 - tuner#1 + * * demod#2-gpio#0 - tuner#2 + * * demod#2-gpio#1 - xtal setting (?) */ struct af9013_platform_data { /* @@ -89,16 +96,15 @@ struct af9013_platform_data { #define AF9013_TS_PARALLEL AF9013_TS_MODE_PARALLEL #define AF9013_TS_SERIAL AF9013_TS_MODE_SERIAL -/* - * AF9013/5 GPIOs (mostly guessed) - * demod#1-gpio#0 - set demod#2 i2c-addr for dual devices - * demod#1-gpio#1 - xtal setting (?) - * demod#1-gpio#3 - tuner#1 - * demod#2-gpio#0 - tuner#2 - * demod#2-gpio#1 - xtal setting (?) - */ - #if IS_REACHABLE(CONFIG_DVB_AF9013) +/** + * Attach an af9013 demod + * + * @config: pointer to &struct af9013_config with demod configuration. + * @i2c: i2c adapter to use. + * + * return: FE pointer on success, NULL on failure. + */ extern struct dvb_frontend *af9013_attach(const struct af9013_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/as102_fe.c b/drivers/media/dvb-frontends/as102_fe.c index 98d575f2744c..b1c84ee914f0 100644 --- a/drivers/media/dvb-frontends/as102_fe.c +++ b/drivers/media/dvb-frontends/as102_fe.c @@ -455,11 +455,10 @@ struct dvb_frontend *as102_attach(const char *name, struct as102_state *state; struct dvb_frontend *fe; - state = kzalloc(sizeof(struct as102_state), GFP_KERNEL); - if (state == NULL) { - pr_err("%s: unable to allocate memory for state\n", __func__); + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) return NULL; - } + fe = &state->frontend; fe->demodulator_priv = state; state->ops = ops; diff --git a/drivers/media/dvb-frontends/ascot2e.h b/drivers/media/dvb-frontends/ascot2e.h index dc61bf7d1b09..418c565baf83 100644 --- a/drivers/media/dvb-frontends/ascot2e.h +++ b/drivers/media/dvb-frontends/ascot2e.h @@ -41,6 +41,15 @@ struct ascot2e_config { }; #if IS_REACHABLE(CONFIG_DVB_ASCOT2E) +/** + * Attach an ascot2e tuner + * + * @fe: frontend to be attached + * @config: pointer to &struct ascot2e_config with tuner configuration. + * @i2c: i2c adapter to use. + * + * return: FE pointer on success, NULL on failure. + */ extern struct dvb_frontend *ascot2e_attach(struct dvb_frontend *fe, const struct ascot2e_config *config, struct i2c_adapter *i2c); diff --git a/drivers/media/dvb-frontends/cx24113.c b/drivers/media/dvb-frontends/cx24113.c index 0118c2658cf7..ee1f704f81f2 100644 --- a/drivers/media/dvb-frontends/cx24113.c +++ b/drivers/media/dvb-frontends/cx24113.c @@ -552,13 +552,11 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, const struct cx24113_config *config, struct i2c_adapter *i2c) { /* allocate memory for the internal state */ - struct cx24113_state *state = - kzalloc(sizeof(struct cx24113_state), GFP_KERNEL); + struct cx24113_state *state = kzalloc(sizeof(*state), GFP_KERNEL); int rc; - if (state == NULL) { - cx_err("Unable to kzalloc\n"); - goto error; - } + + if (!state) + return NULL; /* setup the state */ state->config = config; diff --git a/drivers/media/dvb-frontends/cx24116.c b/drivers/media/dvb-frontends/cx24116.c index e105532bfba8..8fb3f095e21c 100644 --- a/drivers/media/dvb-frontends/cx24116.c +++ b/drivers/media/dvb-frontends/cx24116.c @@ -221,16 +221,13 @@ static int cx24116_writereg(struct cx24116_state *state, int reg, int data) static int cx24116_writeregN(struct cx24116_state *state, int reg, const u8 *data, u16 len) { - int ret = -EREMOTEIO; + int ret; struct i2c_msg msg; u8 *buf; buf = kmalloc(len + 1, GFP_KERNEL); - if (buf == NULL) { - printk("Unable to kmalloc\n"); - ret = -ENOMEM; - goto error; - } + if (!buf) + return -ENOMEM; *(buf) = reg; memcpy(buf + 1, data, len); @@ -251,7 +248,6 @@ static int cx24116_writeregN(struct cx24116_state *state, int reg, ret = -EREMOTEIO; } -error: kfree(buf); return ret; @@ -1121,15 +1117,15 @@ static const struct dvb_frontend_ops cx24116_ops; struct dvb_frontend *cx24116_attach(const struct cx24116_config *config, struct i2c_adapter *i2c) { - struct cx24116_state *state = NULL; + struct cx24116_state *state; int ret; dprintk("%s\n", __func__); /* allocate memory for the internal state */ - state = kzalloc(sizeof(struct cx24116_state), GFP_KERNEL); + state = kzalloc(sizeof(*state), GFP_KERNEL); if (state == NULL) - goto error1; + return NULL; state->config = config; state->i2c = i2c; @@ -1138,8 +1134,9 @@ struct dvb_frontend *cx24116_attach(const struct cx24116_config *config, ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE); if (ret != 0x0501) { + kfree(state); printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n"); - goto error2; + return NULL; } /* create dvb_frontend */ @@ -1147,9 +1144,6 @@ struct dvb_frontend *cx24116_attach(const struct cx24116_config *config, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; - -error2: kfree(state); -error1: return NULL; } EXPORT_SYMBOL(cx24116_attach); diff --git a/drivers/media/dvb-frontends/cxd2820r.h b/drivers/media/dvb-frontends/cxd2820r.h index f3ff8f6eb3bb..a49400c0e28e 100644 --- a/drivers/media/dvb-frontends/cxd2820r.h +++ b/drivers/media/dvb-frontends/cxd2820r.h @@ -49,7 +49,6 @@ * @gpio_chip_base: GPIO. * @get_dvb_frontend: Get DVB frontend. */ - struct cxd2820r_platform_data { u8 ts_mode; bool ts_clk_inv; @@ -62,6 +61,17 @@ struct cxd2820r_platform_data { bool attach_in_use; }; +/** + * struct cxd2820r_config - configuration for cxd2020r demod + * + * @i2c_address: Demodulator I2C address. Driver determines DVB-C slave I2C + * address automatically from master address. + * Default: none, must set. Values: 0x6c, 0x6d. + * @ts_mode: TS output mode. Default: none, must set. Values: FIXME? + * @ts_clock_inv: TS clock inverted. Default: 0. Values: 0, 1. + * @if_agc_polarity: Default: 0. Values: 0, 1 + * @spec_inv: Spectrum inversion. Default: 0. Values: 0, 1. + */ struct cxd2820r_config { /* Demodulator I2C address. * Driver determines DVB-C slave I2C address automatically from master @@ -98,6 +108,18 @@ struct cxd2820r_config { #if IS_REACHABLE(CONFIG_DVB_CXD2820R) +/** + * Attach a cxd2820r demod + * + * @config: pointer to &struct cxd2820r_config with demod configuration. + * @i2c: i2c adapter to use. + * @gpio_chip_base: if zero, disables GPIO setting. Otherwise, if + * CONFIG_GPIOLIB is set dynamically allocate + * gpio base; if is not set, use its value to + * setup the GPIO pins. + * + * return: FE pointer on success, NULL on failure. + */ extern struct dvb_frontend *cxd2820r_attach( const struct cxd2820r_config *config, struct i2c_adapter *i2c, diff --git a/drivers/media/dvb-frontends/drx39xyj/bsp_i2c.h b/drivers/media/dvb-frontends/drx39xyj/bsp_i2c.h index 5b5421f70388..2b3af247a1f1 100644 --- a/drivers/media/dvb-frontends/drx39xyj/bsp_i2c.h +++ b/drivers/media/dvb-frontends/drx39xyj/bsp_i2c.h @@ -52,7 +52,7 @@ struct i2c_device_addr { }; -/** +/* * \def IS_I2C_10BIT( addr ) * \brief Determine if I2C address 'addr' is a 10 bits address or not. * \param addr The I2C address. @@ -67,7 +67,7 @@ struct i2c_device_addr { Exported FUNCTIONS ------------------------------------------------------------------------------*/ -/** +/* * \fn drxbsp_i2c_init() * \brief Initialize I2C communication module. * \return drx_status_t Return status. @@ -76,7 +76,7 @@ Exported FUNCTIONS */ drx_status_t drxbsp_i2c_init(void); -/** +/* * \fn drxbsp_i2c_term() * \brief Terminate I2C communication module. * \return drx_status_t Return status. @@ -85,7 +85,7 @@ Exported FUNCTIONS */ drx_status_t drxbsp_i2c_term(void); -/** +/* * \fn drx_status_t drxbsp_i2c_write_read( struct i2c_device_addr *w_dev_addr, * u16 w_count, * u8 *wData, @@ -121,7 +121,7 @@ Exported FUNCTIONS struct i2c_device_addr *r_dev_addr, u16 r_count, u8 *r_data); -/** +/* * \fn drxbsp_i2c_error_text() * \brief Returns a human readable error. * Counter part of numerical drx_i2c_error_g. @@ -130,7 +130,7 @@ Exported FUNCTIONS */ char *drxbsp_i2c_error_text(void); -/** +/* * \var drx_i2c_error_g; * \brief I2C specific error codes, platform dependent. */ diff --git a/drivers/media/dvb-frontends/drx39xyj/drx_driver.h b/drivers/media/dvb-frontends/drx39xyj/drx_driver.h index cd69e187ba7a..855685b6b386 100644 --- a/drivers/media/dvb-frontends/drx39xyj/drx_driver.h +++ b/drivers/media/dvb-frontends/drx39xyj/drx_driver.h @@ -46,7 +46,7 @@ struct i2c_device_addr { void *user_data; /* User data pointer */ }; -/** +/* * \def IS_I2C_10BIT( addr ) * \brief Determine if I2C address 'addr' is a 10 bits address or not. * \param addr The I2C address. @@ -61,7 +61,7 @@ struct i2c_device_addr { Exported FUNCTIONS ------------------------------------------------------------------------------*/ -/** +/* * \fn drxbsp_i2c_init() * \brief Initialize I2C communication module. * \return int Return status. @@ -70,7 +70,7 @@ Exported FUNCTIONS */ int drxbsp_i2c_init(void); -/** +/* * \fn drxbsp_i2c_term() * \brief Terminate I2C communication module. * \return int Return status. @@ -79,7 +79,7 @@ int drxbsp_i2c_init(void); */ int drxbsp_i2c_term(void); -/** +/* * \fn int drxbsp_i2c_write_read( struct i2c_device_addr *w_dev_addr, * u16 w_count, * u8 * wData, @@ -115,7 +115,7 @@ int drxbsp_i2c_write_read(struct i2c_device_addr *w_dev_addr, struct i2c_device_addr *r_dev_addr, u16 r_count, u8 *r_data); -/** +/* * \fn drxbsp_i2c_error_text() * \brief Returns a human readable error. * Counter part of numerical drx_i2c_error_g. @@ -124,7 +124,7 @@ int drxbsp_i2c_write_read(struct i2c_device_addr *w_dev_addr, */ char *drxbsp_i2c_error_text(void); -/** +/* * \var drx_i2c_error_g; * \brief I2C specific error codes, platform dependent. */ @@ -241,13 +241,13 @@ int drxbsp_tuner_default_i2c_write_read(struct tuner_instance *tuner, struct i2c_device_addr *r_dev_addr, u16 r_count, u8 *r_data); -/************** +/************* * * This section configures the DRX Data Access Protocols (DAPs). * **************/ -/** +/* * \def DRXDAP_SINGLE_MASTER * \brief Enable I2C single or I2C multimaster mode on host. * @@ -262,7 +262,7 @@ int drxbsp_tuner_default_i2c_write_read(struct tuner_instance *tuner, #define DRXDAP_SINGLE_MASTER 1 #endif -/** +/* * \def DRXDAP_MAX_WCHUNKSIZE * \brief Defines maximum chunksize of an i2c write action by host. * @@ -282,7 +282,7 @@ int drxbsp_tuner_default_i2c_write_read(struct tuner_instance *tuner, #define DRXDAP_MAX_WCHUNKSIZE 60 #endif -/** +/* * \def DRXDAP_MAX_RCHUNKSIZE * \brief Defines maximum chunksize of an i2c read action by host. * @@ -297,13 +297,13 @@ int drxbsp_tuner_default_i2c_write_read(struct tuner_instance *tuner, #define DRXDAP_MAX_RCHUNKSIZE 60 #endif -/************** +/************* * * This section describes drxdriver defines. * **************/ -/** +/* * \def DRX_UNKNOWN * \brief Generic UNKNOWN value for DRX enumerated types. * @@ -313,7 +313,7 @@ int drxbsp_tuner_default_i2c_write_read(struct tuner_instance *tuner, #define DRX_UNKNOWN (254) #endif -/** +/* * \def DRX_AUTO * \brief Generic AUTO value for DRX enumerated types. * @@ -324,104 +324,104 @@ int drxbsp_tuner_default_i2c_write_read(struct tuner_instance *tuner, #define DRX_AUTO (255) #endif -/************** +/************* * * This section describes flag definitions for the device capbilities. * **************/ -/** +/* * \brief LNA capability flag * * Device has a Low Noise Amplifier * */ #define DRX_CAPABILITY_HAS_LNA (1UL << 0) -/** +/* * \brief OOB-RX capability flag * * Device has OOB-RX * */ #define DRX_CAPABILITY_HAS_OOBRX (1UL << 1) -/** +/* * \brief ATV capability flag * * Device has ATV * */ #define DRX_CAPABILITY_HAS_ATV (1UL << 2) -/** +/* * \brief DVB-T capability flag * * Device has DVB-T * */ #define DRX_CAPABILITY_HAS_DVBT (1UL << 3) -/** +/* * \brief ITU-B capability flag * * Device has ITU-B * */ #define DRX_CAPABILITY_HAS_ITUB (1UL << 4) -/** +/* * \brief Audio capability flag * * Device has Audio * */ #define DRX_CAPABILITY_HAS_AUD (1UL << 5) -/** +/* * \brief SAW switch capability flag * * Device has SAW switch * */ #define DRX_CAPABILITY_HAS_SAWSW (1UL << 6) -/** +/* * \brief GPIO1 capability flag * * Device has GPIO1 * */ #define DRX_CAPABILITY_HAS_GPIO1 (1UL << 7) -/** +/* * \brief GPIO2 capability flag * * Device has GPIO2 * */ #define DRX_CAPABILITY_HAS_GPIO2 (1UL << 8) -/** +/* * \brief IRQN capability flag * * Device has IRQN * */ #define DRX_CAPABILITY_HAS_IRQN (1UL << 9) -/** +/* * \brief 8VSB capability flag * * Device has 8VSB * */ #define DRX_CAPABILITY_HAS_8VSB (1UL << 10) -/** +/* * \brief SMA-TX capability flag * * Device has SMATX * */ #define DRX_CAPABILITY_HAS_SMATX (1UL << 11) -/** +/* * \brief SMA-RX capability flag * * Device has SMARX * */ #define DRX_CAPABILITY_HAS_SMARX (1UL << 12) -/** +/* * \brief ITU-A/C capability flag * * Device has ITU-A/C @@ -439,7 +439,7 @@ MACROS DRX_VERSIONSTRING_HELP(PATCH) #define DRX_VERSIONSTRING_HELP(NUM) #NUM -/** +/* * \brief Macro to create byte array elements from 16 bit integers. * This macro is used to create byte arrays for block writes. * Block writes speed up I2C traffic between host and demod. @@ -449,7 +449,7 @@ MACROS #define DRX_16TO8(x) ((u8) (((u16)x) & 0xFF)), \ ((u8)((((u16)x)>>8)&0xFF)) -/** +/* * \brief Macro to convert 16 bit register value to a s32 */ #define DRX_U16TODRXFREQ(x) ((x & 0x8000) ? \ @@ -461,191 +461,191 @@ MACROS ENUM -------------------------------------------------------------------------*/ -/** +/* * \enum enum drx_standard * \brief Modulation standards. */ enum drx_standard { - DRX_STANDARD_DVBT = 0, /**< Terrestrial DVB-T. */ - DRX_STANDARD_8VSB, /**< Terrestrial 8VSB. */ - DRX_STANDARD_NTSC, /**< Terrestrial\Cable analog NTSC. */ + DRX_STANDARD_DVBT = 0, /*< Terrestrial DVB-T. */ + DRX_STANDARD_8VSB, /*< Terrestrial 8VSB. */ + DRX_STANDARD_NTSC, /*< Terrestrial\Cable analog NTSC. */ DRX_STANDARD_PAL_SECAM_BG, - /**< Terrestrial analog PAL/SECAM B/G */ + /*< Terrestrial analog PAL/SECAM B/G */ DRX_STANDARD_PAL_SECAM_DK, - /**< Terrestrial analog PAL/SECAM D/K */ + /*< Terrestrial analog PAL/SECAM D/K */ DRX_STANDARD_PAL_SECAM_I, - /**< Terrestrial analog PAL/SECAM I */ + /*< Terrestrial analog PAL/SECAM I */ DRX_STANDARD_PAL_SECAM_L, - /**< Terrestrial analog PAL/SECAM L + /*< Terrestrial analog PAL/SECAM L with negative modulation */ DRX_STANDARD_PAL_SECAM_LP, - /**< Terrestrial analog PAL/SECAM L + /*< Terrestrial analog PAL/SECAM L with positive modulation */ - DRX_STANDARD_ITU_A, /**< Cable ITU ANNEX A. */ - DRX_STANDARD_ITU_B, /**< Cable ITU ANNEX B. */ - DRX_STANDARD_ITU_C, /**< Cable ITU ANNEX C. */ - DRX_STANDARD_ITU_D, /**< Cable ITU ANNEX D. */ - DRX_STANDARD_FM, /**< Terrestrial\Cable FM radio */ - DRX_STANDARD_DTMB, /**< Terrestrial DTMB standard (China)*/ + DRX_STANDARD_ITU_A, /*< Cable ITU ANNEX A. */ + DRX_STANDARD_ITU_B, /*< Cable ITU ANNEX B. */ + DRX_STANDARD_ITU_C, /*< Cable ITU ANNEX C. */ + DRX_STANDARD_ITU_D, /*< Cable ITU ANNEX D. */ + DRX_STANDARD_FM, /*< Terrestrial\Cable FM radio */ + DRX_STANDARD_DTMB, /*< Terrestrial DTMB standard (China)*/ DRX_STANDARD_UNKNOWN = DRX_UNKNOWN, - /**< Standard unknown. */ + /*< Standard unknown. */ DRX_STANDARD_AUTO = DRX_AUTO - /**< Autodetect standard. */ + /*< Autodetect standard. */ }; -/** +/* * \enum enum drx_standard * \brief Modulation sub-standards. */ enum drx_substandard { - DRX_SUBSTANDARD_MAIN = 0, /**< Main subvariant of standard */ + DRX_SUBSTANDARD_MAIN = 0, /*< Main subvariant of standard */ DRX_SUBSTANDARD_ATV_BG_SCANDINAVIA, DRX_SUBSTANDARD_ATV_DK_POLAND, DRX_SUBSTANDARD_ATV_DK_CHINA, DRX_SUBSTANDARD_UNKNOWN = DRX_UNKNOWN, - /**< Sub-standard unknown. */ + /*< Sub-standard unknown. */ DRX_SUBSTANDARD_AUTO = DRX_AUTO - /**< Auto (default) sub-standard */ + /*< Auto (default) sub-standard */ }; -/** +/* * \enum enum drx_bandwidth * \brief Channel bandwidth or channel spacing. */ enum drx_bandwidth { - DRX_BANDWIDTH_8MHZ = 0, /**< Bandwidth 8 MHz. */ - DRX_BANDWIDTH_7MHZ, /**< Bandwidth 7 MHz. */ - DRX_BANDWIDTH_6MHZ, /**< Bandwidth 6 MHz. */ + DRX_BANDWIDTH_8MHZ = 0, /*< Bandwidth 8 MHz. */ + DRX_BANDWIDTH_7MHZ, /*< Bandwidth 7 MHz. */ + DRX_BANDWIDTH_6MHZ, /*< Bandwidth 6 MHz. */ DRX_BANDWIDTH_UNKNOWN = DRX_UNKNOWN, - /**< Bandwidth unknown. */ + /*< Bandwidth unknown. */ DRX_BANDWIDTH_AUTO = DRX_AUTO - /**< Auto Set Bandwidth */ + /*< Auto Set Bandwidth */ }; -/** +/* * \enum enum drx_mirror * \brief Indicate if channel spectrum is mirrored or not. */ enum drx_mirror { - DRX_MIRROR_NO = 0, /**< Spectrum is not mirrored. */ - DRX_MIRROR_YES, /**< Spectrum is mirrored. */ + DRX_MIRROR_NO = 0, /*< Spectrum is not mirrored. */ + DRX_MIRROR_YES, /*< Spectrum is mirrored. */ DRX_MIRROR_UNKNOWN = DRX_UNKNOWN, - /**< Unknown if spectrum is mirrored. */ + /*< Unknown if spectrum is mirrored. */ DRX_MIRROR_AUTO = DRX_AUTO - /**< Autodetect if spectrum is mirrored. */ + /*< Autodetect if spectrum is mirrored. */ }; -/** +/* * \enum enum drx_modulation * \brief Constellation type of the channel. */ enum drx_modulation { - DRX_CONSTELLATION_BPSK = 0, /**< Modulation is BPSK. */ - DRX_CONSTELLATION_QPSK, /**< Constellation is QPSK. */ - DRX_CONSTELLATION_PSK8, /**< Constellation is PSK8. */ - DRX_CONSTELLATION_QAM16, /**< Constellation is QAM16. */ - DRX_CONSTELLATION_QAM32, /**< Constellation is QAM32. */ - DRX_CONSTELLATION_QAM64, /**< Constellation is QAM64. */ - DRX_CONSTELLATION_QAM128, /**< Constellation is QAM128. */ - DRX_CONSTELLATION_QAM256, /**< Constellation is QAM256. */ - DRX_CONSTELLATION_QAM512, /**< Constellation is QAM512. */ - DRX_CONSTELLATION_QAM1024, /**< Constellation is QAM1024. */ - DRX_CONSTELLATION_QPSK_NR, /**< Constellation is QPSK_NR */ + DRX_CONSTELLATION_BPSK = 0, /*< Modulation is BPSK. */ + DRX_CONSTELLATION_QPSK, /*< Constellation is QPSK. */ + DRX_CONSTELLATION_PSK8, /*< Constellation is PSK8. */ + DRX_CONSTELLATION_QAM16, /*< Constellation is QAM16. */ + DRX_CONSTELLATION_QAM32, /*< Constellation is QAM32. */ + DRX_CONSTELLATION_QAM64, /*< Constellation is QAM64. */ + DRX_CONSTELLATION_QAM128, /*< Constellation is QAM128. */ + DRX_CONSTELLATION_QAM256, /*< Constellation is QAM256. */ + DRX_CONSTELLATION_QAM512, /*< Constellation is QAM512. */ + DRX_CONSTELLATION_QAM1024, /*< Constellation is QAM1024. */ + DRX_CONSTELLATION_QPSK_NR, /*< Constellation is QPSK_NR */ DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN, - /**< Constellation unknown. */ + /*< Constellation unknown. */ DRX_CONSTELLATION_AUTO = DRX_AUTO - /**< Autodetect constellation. */ + /*< Autodetect constellation. */ }; -/** +/* * \enum enum drx_hierarchy * \brief Hierarchy of the channel. */ enum drx_hierarchy { - DRX_HIERARCHY_NONE = 0, /**< None hierarchical channel. */ - DRX_HIERARCHY_ALPHA1, /**< Hierarchical channel, alpha=1. */ - DRX_HIERARCHY_ALPHA2, /**< Hierarchical channel, alpha=2. */ - DRX_HIERARCHY_ALPHA4, /**< Hierarchical channel, alpha=4. */ + DRX_HIERARCHY_NONE = 0, /*< None hierarchical channel. */ + DRX_HIERARCHY_ALPHA1, /*< Hierarchical channel, alpha=1. */ + DRX_HIERARCHY_ALPHA2, /*< Hierarchical channel, alpha=2. */ + DRX_HIERARCHY_ALPHA4, /*< Hierarchical channel, alpha=4. */ DRX_HIERARCHY_UNKNOWN = DRX_UNKNOWN, - /**< Hierarchy unknown. */ + /*< Hierarchy unknown. */ DRX_HIERARCHY_AUTO = DRX_AUTO - /**< Autodetect hierarchy. */ + /*< Autodetect hierarchy. */ }; -/** +/* * \enum enum drx_priority * \brief Channel priority in case of hierarchical transmission. */ enum drx_priority { - DRX_PRIORITY_LOW = 0, /**< Low priority channel. */ - DRX_PRIORITY_HIGH, /**< High priority channel. */ + DRX_PRIORITY_LOW = 0, /*< Low priority channel. */ + DRX_PRIORITY_HIGH, /*< High priority channel. */ DRX_PRIORITY_UNKNOWN = DRX_UNKNOWN - /**< Priority unknown. */ + /*< Priority unknown. */ }; -/** +/* * \enum enum drx_coderate * \brief Channel priority in case of hierarchical transmission. */ enum drx_coderate { - DRX_CODERATE_1DIV2 = 0, /**< Code rate 1/2nd. */ - DRX_CODERATE_2DIV3, /**< Code rate 2/3nd. */ - DRX_CODERATE_3DIV4, /**< Code rate 3/4nd. */ - DRX_CODERATE_5DIV6, /**< Code rate 5/6nd. */ - DRX_CODERATE_7DIV8, /**< Code rate 7/8nd. */ + DRX_CODERATE_1DIV2 = 0, /*< Code rate 1/2nd. */ + DRX_CODERATE_2DIV3, /*< Code rate 2/3nd. */ + DRX_CODERATE_3DIV4, /*< Code rate 3/4nd. */ + DRX_CODERATE_5DIV6, /*< Code rate 5/6nd. */ + DRX_CODERATE_7DIV8, /*< Code rate 7/8nd. */ DRX_CODERATE_UNKNOWN = DRX_UNKNOWN, - /**< Code rate unknown. */ + /*< Code rate unknown. */ DRX_CODERATE_AUTO = DRX_AUTO - /**< Autodetect code rate. */ + /*< Autodetect code rate. */ }; -/** +/* * \enum enum drx_guard * \brief Guard interval of a channel. */ enum drx_guard { - DRX_GUARD_1DIV32 = 0, /**< Guard interval 1/32nd. */ - DRX_GUARD_1DIV16, /**< Guard interval 1/16th. */ - DRX_GUARD_1DIV8, /**< Guard interval 1/8th. */ - DRX_GUARD_1DIV4, /**< Guard interval 1/4th. */ + DRX_GUARD_1DIV32 = 0, /*< Guard interval 1/32nd. */ + DRX_GUARD_1DIV16, /*< Guard interval 1/16th. */ + DRX_GUARD_1DIV8, /*< Guard interval 1/8th. */ + DRX_GUARD_1DIV4, /*< Guard interval 1/4th. */ DRX_GUARD_UNKNOWN = DRX_UNKNOWN, - /**< Guard interval unknown. */ + /*< Guard interval unknown. */ DRX_GUARD_AUTO = DRX_AUTO - /**< Autodetect guard interval. */ + /*< Autodetect guard interval. */ }; -/** +/* * \enum enum drx_fft_mode * \brief FFT mode. */ enum drx_fft_mode { - DRX_FFTMODE_2K = 0, /**< 2K FFT mode. */ - DRX_FFTMODE_4K, /**< 4K FFT mode. */ - DRX_FFTMODE_8K, /**< 8K FFT mode. */ + DRX_FFTMODE_2K = 0, /*< 2K FFT mode. */ + DRX_FFTMODE_4K, /*< 4K FFT mode. */ + DRX_FFTMODE_8K, /*< 8K FFT mode. */ DRX_FFTMODE_UNKNOWN = DRX_UNKNOWN, - /**< FFT mode unknown. */ + /*< FFT mode unknown. */ DRX_FFTMODE_AUTO = DRX_AUTO - /**< Autodetect FFT mode. */ + /*< Autodetect FFT mode. */ }; -/** +/* * \enum enum drx_classification * \brief Channel classification. */ enum drx_classification { - DRX_CLASSIFICATION_GAUSS = 0, /**< Gaussion noise. */ - DRX_CLASSIFICATION_HVY_GAUSS, /**< Heavy Gaussion noise. */ - DRX_CLASSIFICATION_COCHANNEL, /**< Co-channel. */ - DRX_CLASSIFICATION_STATIC, /**< Static echo. */ - DRX_CLASSIFICATION_MOVING, /**< Moving echo. */ - DRX_CLASSIFICATION_ZERODB, /**< Zero dB echo. */ + DRX_CLASSIFICATION_GAUSS = 0, /*< Gaussion noise. */ + DRX_CLASSIFICATION_HVY_GAUSS, /*< Heavy Gaussion noise. */ + DRX_CLASSIFICATION_COCHANNEL, /*< Co-channel. */ + DRX_CLASSIFICATION_STATIC, /*< Static echo. */ + DRX_CLASSIFICATION_MOVING, /*< Moving echo. */ + DRX_CLASSIFICATION_ZERODB, /*< Zero dB echo. */ DRX_CLASSIFICATION_UNKNOWN = DRX_UNKNOWN, - /**< Unknown classification */ + /*< Unknown classification */ DRX_CLASSIFICATION_AUTO = DRX_AUTO - /**< Autodetect classification. */ + /*< Autodetect classification. */ }; -/** +/* * /enum enum drx_interleave_mode * /brief Interleave modes */ @@ -673,80 +673,80 @@ enum drx_interleave_mode { DRX_INTERLEAVEMODE_B52_M48, DRX_INTERLEAVEMODE_B52_M0, DRX_INTERLEAVEMODE_UNKNOWN = DRX_UNKNOWN, - /**< Unknown interleave mode */ + /*< Unknown interleave mode */ DRX_INTERLEAVEMODE_AUTO = DRX_AUTO - /**< Autodetect interleave mode */ + /*< Autodetect interleave mode */ }; -/** +/* * \enum enum drx_carrier_mode * \brief Channel Carrier Mode. */ enum drx_carrier_mode { - DRX_CARRIER_MULTI = 0, /**< Multi carrier mode */ - DRX_CARRIER_SINGLE, /**< Single carrier mode */ + DRX_CARRIER_MULTI = 0, /*< Multi carrier mode */ + DRX_CARRIER_SINGLE, /*< Single carrier mode */ DRX_CARRIER_UNKNOWN = DRX_UNKNOWN, - /**< Carrier mode unknown. */ - DRX_CARRIER_AUTO = DRX_AUTO /**< Autodetect carrier mode */ + /*< Carrier mode unknown. */ + DRX_CARRIER_AUTO = DRX_AUTO /*< Autodetect carrier mode */ }; -/** +/* * \enum enum drx_frame_mode * \brief Channel Frame Mode. */ enum drx_frame_mode { - DRX_FRAMEMODE_420 = 0, /**< 420 with variable PN */ - DRX_FRAMEMODE_595, /**< 595 */ - DRX_FRAMEMODE_945, /**< 945 with variable PN */ + DRX_FRAMEMODE_420 = 0, /*< 420 with variable PN */ + DRX_FRAMEMODE_595, /*< 595 */ + DRX_FRAMEMODE_945, /*< 945 with variable PN */ DRX_FRAMEMODE_420_FIXED_PN, - /**< 420 with fixed PN */ + /*< 420 with fixed PN */ DRX_FRAMEMODE_945_FIXED_PN, - /**< 945 with fixed PN */ + /*< 945 with fixed PN */ DRX_FRAMEMODE_UNKNOWN = DRX_UNKNOWN, - /**< Frame mode unknown. */ + /*< Frame mode unknown. */ DRX_FRAMEMODE_AUTO = DRX_AUTO - /**< Autodetect frame mode */ + /*< Autodetect frame mode */ }; -/** +/* * \enum enum drx_tps_frame * \brief Frame number in current super-frame. */ enum drx_tps_frame { - DRX_TPS_FRAME1 = 0, /**< TPS frame 1. */ - DRX_TPS_FRAME2, /**< TPS frame 2. */ - DRX_TPS_FRAME3, /**< TPS frame 3. */ - DRX_TPS_FRAME4, /**< TPS frame 4. */ + DRX_TPS_FRAME1 = 0, /*< TPS frame 1. */ + DRX_TPS_FRAME2, /*< TPS frame 2. */ + DRX_TPS_FRAME3, /*< TPS frame 3. */ + DRX_TPS_FRAME4, /*< TPS frame 4. */ DRX_TPS_FRAME_UNKNOWN = DRX_UNKNOWN - /**< TPS frame unknown. */ + /*< TPS frame unknown. */ }; -/** +/* * \enum enum drx_ldpc * \brief TPS LDPC . */ enum drx_ldpc { - DRX_LDPC_0_4 = 0, /**< LDPC 0.4 */ - DRX_LDPC_0_6, /**< LDPC 0.6 */ - DRX_LDPC_0_8, /**< LDPC 0.8 */ + DRX_LDPC_0_4 = 0, /*< LDPC 0.4 */ + DRX_LDPC_0_6, /*< LDPC 0.6 */ + DRX_LDPC_0_8, /*< LDPC 0.8 */ DRX_LDPC_UNKNOWN = DRX_UNKNOWN, - /**< LDPC unknown. */ - DRX_LDPC_AUTO = DRX_AUTO /**< Autodetect LDPC */ + /*< LDPC unknown. */ + DRX_LDPC_AUTO = DRX_AUTO /*< Autodetect LDPC */ }; -/** +/* * \enum enum drx_pilot_mode * \brief Pilot modes in DTMB. */ enum drx_pilot_mode { - DRX_PILOT_ON = 0, /**< Pilot On */ - DRX_PILOT_OFF, /**< Pilot Off */ + DRX_PILOT_ON = 0, /*< Pilot On */ + DRX_PILOT_OFF, /*< Pilot Off */ DRX_PILOT_UNKNOWN = DRX_UNKNOWN, - /**< Pilot unknown. */ - DRX_PILOT_AUTO = DRX_AUTO /**< Autodetect Pilot */ + /*< Pilot unknown. */ + DRX_PILOT_AUTO = DRX_AUTO /*< Autodetect Pilot */ }; -/** +/* * enum drxu_code_action - indicate if firmware has to be uploaded or verified. * @UCODE_UPLOAD: Upload the microcode image to device * @UCODE_VERIFY: Compare microcode image with code on device @@ -756,7 +756,7 @@ enum drxu_code_action { UCODE_VERIFY }; -/** +/* * \enum enum drx_lock_status * \brief Used to reflect current lock status of demodulator. * * The generic lock states have device dependent semantics. @@ -801,7 +801,7 @@ enum drx_lock_status { DRX_LOCKED }; -/** +/* * \enum enum drx_uio* \brief Used to address a User IO (UIO). */ enum drx_uio { @@ -840,7 +840,7 @@ enum drx_uio { DRX_UIO_MAX = DRX_UIO32 }; -/** +/* * \enum enum drxuio_mode * \brief Used to configure the modus oprandi of a UIO. * * DRX_UIO_MODE_FIRMWARE is an old uio mode. @@ -850,37 +850,37 @@ enum drx_uio { */ enum drxuio_mode { DRX_UIO_MODE_DISABLE = 0x01, - /**< not used, pin is configured as input */ + /*< not used, pin is configured as input */ DRX_UIO_MODE_READWRITE = 0x02, - /**< used for read/write by application */ + /*< used for read/write by application */ DRX_UIO_MODE_FIRMWARE = 0x04, - /**< controlled by firmware, function 0 */ + /*< controlled by firmware, function 0 */ DRX_UIO_MODE_FIRMWARE0 = DRX_UIO_MODE_FIRMWARE, - /**< same as above */ + /*< same as above */ DRX_UIO_MODE_FIRMWARE1 = 0x08, - /**< controlled by firmware, function 1 */ + /*< controlled by firmware, function 1 */ DRX_UIO_MODE_FIRMWARE2 = 0x10, - /**< controlled by firmware, function 2 */ + /*< controlled by firmware, function 2 */ DRX_UIO_MODE_FIRMWARE3 = 0x20, - /**< controlled by firmware, function 3 */ + /*< controlled by firmware, function 3 */ DRX_UIO_MODE_FIRMWARE4 = 0x40, - /**< controlled by firmware, function 4 */ + /*< controlled by firmware, function 4 */ DRX_UIO_MODE_FIRMWARE5 = 0x80 - /**< controlled by firmware, function 5 */ + /*< controlled by firmware, function 5 */ }; -/** +/* * \enum enum drxoob_downstream_standard * \brief Used to select OOB standard. * * Based on ANSI 55-1 and 55-2 */ enum drxoob_downstream_standard { DRX_OOB_MODE_A = 0, - /**< ANSI 55-1 */ + /*< ANSI 55-1 */ DRX_OOB_MODE_B_GRADE_A, - /**< ANSI 55-2 A */ + /*< ANSI 55-2 A */ DRX_OOB_MODE_B_GRADE_B - /**< ANSI 55-2 B */ + /*< ANSI 55-2 B */ }; /*------------------------------------------------------------------------- @@ -924,7 +924,7 @@ STRUCTS /*============================================================================*/ /*============================================================================*/ -/** +/* * struct drxu_code_info Parameters for microcode upload and verfiy. * * @mc_file: microcode file name @@ -935,7 +935,7 @@ struct drxu_code_info { char *mc_file; }; -/** +/* * \struct drx_mc_version_rec_t * \brief Microcode version record * Version numbers are stored in BCD format, as usual: @@ -963,7 +963,7 @@ struct drx_mc_version_rec { /*========================================*/ -/** +/* * \struct drx_filter_info_t * \brief Parameters for loading filter coefficients * @@ -971,18 +971,18 @@ struct drx_mc_version_rec { */ struct drx_filter_info { u8 *data_re; - /**< pointer to coefficients for RE */ + /*< pointer to coefficients for RE */ u8 *data_im; - /**< pointer to coefficients for IM */ + /*< pointer to coefficients for IM */ u16 size_re; - /**< size of coefficients for RE */ + /*< size of coefficients for RE */ u16 size_im; - /**< size of coefficients for IM */ + /*< size of coefficients for IM */ }; /*========================================*/ -/** +/* * \struct struct drx_channel * \brief The set of parameters describing a single channel. * * Used by DRX_CTRL_SET_CHANNEL and DRX_CTRL_GET_CHANNEL. @@ -991,29 +991,29 @@ struct drx_filter_info { */ struct drx_channel { s32 frequency; - /**< frequency in kHz */ + /*< frequency in kHz */ enum drx_bandwidth bandwidth; - /**< bandwidth */ - enum drx_mirror mirror; /**< mirrored or not on RF */ + /*< bandwidth */ + enum drx_mirror mirror; /*< mirrored or not on RF */ enum drx_modulation constellation; - /**< constellation */ + /*< constellation */ enum drx_hierarchy hierarchy; - /**< hierarchy */ - enum drx_priority priority; /**< priority */ - enum drx_coderate coderate; /**< coderate */ - enum drx_guard guard; /**< guard interval */ - enum drx_fft_mode fftmode; /**< fftmode */ + /*< hierarchy */ + enum drx_priority priority; /*< priority */ + enum drx_coderate coderate; /*< coderate */ + enum drx_guard guard; /*< guard interval */ + enum drx_fft_mode fftmode; /*< fftmode */ enum drx_classification classification; - /**< classification */ + /*< classification */ u32 symbolrate; - /**< symbolrate in symbols/sec */ + /*< symbolrate in symbols/sec */ enum drx_interleave_mode interleavemode; - /**< interleaveMode QAM */ - enum drx_ldpc ldpc; /**< ldpc */ - enum drx_carrier_mode carrier; /**< carrier */ + /*< interleaveMode QAM */ + enum drx_ldpc ldpc; /*< ldpc */ + enum drx_carrier_mode carrier; /*< carrier */ enum drx_frame_mode framemode; - /**< frame mode */ - enum drx_pilot_mode pilot; /**< pilot mode */ + /*< frame mode */ + enum drx_pilot_mode pilot; /*< pilot mode */ }; /*========================================*/ @@ -1027,74 +1027,74 @@ enum drx_cfg_sqi_speed { /*========================================*/ -/** +/* * \struct struct drx_complex * A complex number. * * Used by DRX_CTRL_CONSTEL. */ struct drx_complex { s16 im; - /**< Imaginary part. */ + /*< Imaginary part. */ s16 re; - /**< Real part. */ + /*< Real part. */ }; /*========================================*/ -/** +/* * \struct struct drx_frequency_plan * Array element of a frequency plan. * * Used by DRX_CTRL_SCAN_INIT. */ struct drx_frequency_plan { s32 first; - /**< First centre frequency in this band */ + /*< First centre frequency in this band */ s32 last; - /**< Last centre frequency in this band */ + /*< Last centre frequency in this band */ s32 step; - /**< Stepping frequency in this band */ + /*< Stepping frequency in this band */ enum drx_bandwidth bandwidth; - /**< Bandwidth within this frequency band */ + /*< Bandwidth within this frequency band */ u16 ch_number; - /**< First channel number in this band, or first + /*< First channel number in this band, or first index in ch_names */ char **ch_names; - /**< Optional list of channel names in this + /*< Optional list of channel names in this band */ }; /*========================================*/ -/** +/* * \struct struct drx_scan_param * Parameters for channel scan. * * Used by DRX_CTRL_SCAN_INIT. */ struct drx_scan_param { struct drx_frequency_plan *frequency_plan; - /**< Frequency plan (array)*/ - u16 frequency_plan_size; /**< Number of bands */ - u32 num_tries; /**< Max channels tried */ - s32 skip; /**< Minimum frequency step to take + /*< Frequency plan (array)*/ + u16 frequency_plan_size; /*< Number of bands */ + u32 num_tries; /*< Max channels tried */ + s32 skip; /*< Minimum frequency step to take after a channel is found */ - void *ext_params; /**< Standard specific params */ + void *ext_params; /*< Standard specific params */ }; /*========================================*/ -/** +/* * \brief Scan commands. * Used by scanning algorithms. */ enum drx_scan_command { - DRX_SCAN_COMMAND_INIT = 0,/**< Initialize scanning */ - DRX_SCAN_COMMAND_NEXT, /**< Next scan */ - DRX_SCAN_COMMAND_STOP /**< Stop scanning */ + DRX_SCAN_COMMAND_INIT = 0,/*< Initialize scanning */ + DRX_SCAN_COMMAND_NEXT, /*< Next scan */ + DRX_SCAN_COMMAND_STOP /*< Stop scanning */ }; /*========================================*/ -/** +/* * \brief Inner scan function prototype. */ typedef int(*drx_scan_func_t) (void *scan_context, @@ -1104,77 +1104,77 @@ typedef int(*drx_scan_func_t) (void *scan_context, /*========================================*/ -/** +/* * \struct struct drxtps_info * TPS information, DVB-T specific. * * Used by DRX_CTRL_TPS_INFO. */ struct drxtps_info { - enum drx_fft_mode fftmode; /**< Fft mode */ - enum drx_guard guard; /**< Guard interval */ + enum drx_fft_mode fftmode; /*< Fft mode */ + enum drx_guard guard; /*< Guard interval */ enum drx_modulation constellation; - /**< Constellation */ + /*< Constellation */ enum drx_hierarchy hierarchy; - /**< Hierarchy */ + /*< Hierarchy */ enum drx_coderate high_coderate; - /**< High code rate */ + /*< High code rate */ enum drx_coderate low_coderate; - /**< Low cod rate */ - enum drx_tps_frame frame; /**< Tps frame */ - u8 length; /**< Length */ - u16 cell_id; /**< Cell id */ + /*< Low cod rate */ + enum drx_tps_frame frame; /*< Tps frame */ + u8 length; /*< Length */ + u16 cell_id; /*< Cell id */ }; /*========================================*/ -/** +/* * \brief Power mode of device. * * Used by DRX_CTRL_SET_POWER_MODE. */ enum drx_power_mode { DRX_POWER_UP = 0, - /**< Generic , Power Up Mode */ + /*< Generic , Power Up Mode */ DRX_POWER_MODE_1, - /**< Device specific , Power Up Mode */ + /*< Device specific , Power Up Mode */ DRX_POWER_MODE_2, - /**< Device specific , Power Up Mode */ + /*< Device specific , Power Up Mode */ DRX_POWER_MODE_3, - /**< Device specific , Power Up Mode */ + /*< Device specific , Power Up Mode */ DRX_POWER_MODE_4, - /**< Device specific , Power Up Mode */ + /*< Device specific , Power Up Mode */ DRX_POWER_MODE_5, - /**< Device specific , Power Up Mode */ + /*< Device specific , Power Up Mode */ DRX_POWER_MODE_6, - /**< Device specific , Power Up Mode */ + /*< Device specific , Power Up Mode */ DRX_POWER_MODE_7, - /**< Device specific , Power Up Mode */ + /*< Device specific , Power Up Mode */ DRX_POWER_MODE_8, - /**< Device specific , Power Up Mode */ + /*< Device specific , Power Up Mode */ DRX_POWER_MODE_9, - /**< Device specific , Power Down Mode */ + /*< Device specific , Power Down Mode */ DRX_POWER_MODE_10, - /**< Device specific , Power Down Mode */ + /*< Device specific , Power Down Mode */ DRX_POWER_MODE_11, - /**< Device specific , Power Down Mode */ + /*< Device specific , Power Down Mode */ DRX_POWER_MODE_12, - /**< Device specific , Power Down Mode */ + /*< Device specific , Power Down Mode */ DRX_POWER_MODE_13, - /**< Device specific , Power Down Mode */ + /*< Device specific , Power Down Mode */ DRX_POWER_MODE_14, - /**< Device specific , Power Down Mode */ + /*< Device specific , Power Down Mode */ DRX_POWER_MODE_15, - /**< Device specific , Power Down Mode */ + /*< Device specific , Power Down Mode */ DRX_POWER_MODE_16, - /**< Device specific , Power Down Mode */ + /*< Device specific , Power Down Mode */ DRX_POWER_DOWN = 255 - /**< Generic , Power Down Mode */ + /*< Generic , Power Down Mode */ }; /*========================================*/ -/** +/* * \enum enum drx_module * \brief Software module identification. * * Used by DRX_CTRL_VERSION. @@ -1191,93 +1191,93 @@ typedef int(*drx_scan_func_t) (void *scan_context, DRX_MODULE_UNKNOWN }; -/** +/* * \enum struct drx_version * \brief Version information of one software module. * * Used by DRX_CTRL_VERSION. */ struct drx_version { enum drx_module module_type; - /**< Type identifier of the module */ + /*< Type identifier of the module */ char *module_name; - /**< Name or description of module */ - u16 v_major; /**< Major version number */ - u16 v_minor; /**< Minor version number */ - u16 v_patch; /**< Patch version number */ - char *v_string; /**< Version as text string */ + /*< Name or description of module */ + u16 v_major; /*< Major version number */ + u16 v_minor; /*< Minor version number */ + u16 v_patch; /*< Patch version number */ + char *v_string; /*< Version as text string */ }; -/** +/* * \enum struct drx_version_list * \brief List element of NULL terminated, linked list for version information. * * Used by DRX_CTRL_VERSION. */ struct drx_version_list { - struct drx_version *version;/**< Version information */ + struct drx_version *version;/*< Version information */ struct drx_version_list *next; - /**< Next list element */ + /*< Next list element */ }; /*========================================*/ -/** +/* * \brief Parameters needed to confiugure a UIO. * * Used by DRX_CTRL_UIO_CFG. */ struct drxuio_cfg { enum drx_uio uio; - /**< UIO identifier */ + /*< UIO identifier */ enum drxuio_mode mode; - /**< UIO operational mode */ + /*< UIO operational mode */ }; /*========================================*/ -/** +/* * \brief Parameters needed to read from or write to a UIO. * * Used by DRX_CTRL_UIO_READ and DRX_CTRL_UIO_WRITE. */ struct drxuio_data { enum drx_uio uio; - /**< UIO identifier */ + /*< UIO identifier */ bool value; - /**< UIO value (true=1, false=0) */ + /*< UIO value (true=1, false=0) */ }; /*========================================*/ -/** +/* * \brief Parameters needed to configure OOB. * * Used by DRX_CTRL_SET_OOB. */ struct drxoob { - s32 frequency; /**< Frequency in kHz */ + s32 frequency; /*< Frequency in kHz */ enum drxoob_downstream_standard standard; - /**< OOB standard */ - bool spectrum_inverted; /**< If true, then spectrum + /*< OOB standard */ + bool spectrum_inverted; /*< If true, then spectrum is inverted */ }; /*========================================*/ -/** +/* * \brief Metrics from OOB. * * Used by DRX_CTRL_GET_OOB. */ struct drxoob_status { - s32 frequency; /**< Frequency in Khz */ - enum drx_lock_status lock; /**< Lock status */ - u32 mer; /**< MER */ - s32 symbol_rate_offset; /**< Symbolrate offset in ppm */ + s32 frequency; /*< Frequency in Khz */ + enum drx_lock_status lock; /*< Lock status */ + u32 mer; /*< MER */ + s32 symbol_rate_offset; /*< Symbolrate offset in ppm */ }; /*========================================*/ -/** +/* * \brief Device dependent configuration data. * * Used by DRX_CTRL_SET_CFG and DRX_CTRL_GET_CFG. @@ -1285,14 +1285,14 @@ struct drx_version_list { */ struct drx_cfg { u32 cfg_type; - /**< Function identifier */ + /*< Function identifier */ void *cfg_data; - /**< Function data */ + /*< Function data */ }; /*========================================*/ -/** +/* * /struct DRXMpegStartWidth_t * MStart width [nr MCLK cycles] for serial MPEG output. */ @@ -1303,7 +1303,7 @@ struct drx_version_list { }; /* CTRL CFG MPEG output */ -/** +/* * \struct struct drx_cfg_mpeg_output * \brief Configuration parameters for MPEG output control. * * Used by DRX_CFG_MPEG_OUTPUT, in combination with DRX_CTRL_SET_CFG and @@ -1311,29 +1311,29 @@ struct drx_version_list { */ struct drx_cfg_mpeg_output { - bool enable_mpeg_output;/**< If true, enable MPEG output */ - bool insert_rs_byte; /**< If true, insert RS byte */ - bool enable_parallel; /**< If true, parallel out otherwise + bool enable_mpeg_output;/*< If true, enable MPEG output */ + bool insert_rs_byte; /*< If true, insert RS byte */ + bool enable_parallel; /*< If true, parallel out otherwise serial */ - bool invert_data; /**< If true, invert DATA signals */ - bool invert_err; /**< If true, invert ERR signal */ - bool invert_str; /**< If true, invert STR signals */ - bool invert_val; /**< If true, invert VAL signals */ - bool invert_clk; /**< If true, invert CLK signals */ - bool static_clk; /**< If true, static MPEG clockrate + bool invert_data; /*< If true, invert DATA signals */ + bool invert_err; /*< If true, invert ERR signal */ + bool invert_str; /*< If true, invert STR signals */ + bool invert_val; /*< If true, invert VAL signals */ + bool invert_clk; /*< If true, invert CLK signals */ + bool static_clk; /*< If true, static MPEG clockrate will be used, otherwise clockrate will adapt to the bitrate of the TS */ - u32 bitrate; /**< Maximum bitrate in b/s in case + u32 bitrate; /*< Maximum bitrate in b/s in case static clockrate is selected */ enum drxmpeg_str_width width_str; - /**< MPEG start width */ + /*< MPEG start width */ }; /*========================================*/ -/** +/* * \struct struct drxi2c_data * \brief Data for I2C via 2nd or 3rd or etc I2C port. * * Used by DRX_CTRL_I2C_READWRITE. @@ -1341,187 +1341,187 @@ struct drx_version_list { * */ struct drxi2c_data { - u16 port_nr; /**< I2C port number */ + u16 port_nr; /*< I2C port number */ struct i2c_device_addr *w_dev_addr; - /**< Write device address */ - u16 w_count; /**< Size of write data in bytes */ - u8 *wData; /**< Pointer to write data */ + /*< Write device address */ + u16 w_count; /*< Size of write data in bytes */ + u8 *wData; /*< Pointer to write data */ struct i2c_device_addr *r_dev_addr; - /**< Read device address */ - u16 r_count; /**< Size of data to read in bytes */ - u8 *r_data; /**< Pointer to read buffer */ + /*< Read device address */ + u16 r_count; /*< Size of data to read in bytes */ + u8 *r_data; /*< Pointer to read buffer */ }; /*========================================*/ -/** +/* * \enum enum drx_aud_standard * \brief Audio standard identifier. * * Used by DRX_CTRL_SET_AUD. */ enum drx_aud_standard { - DRX_AUD_STANDARD_BTSC, /**< set BTSC standard (USA) */ - DRX_AUD_STANDARD_A2, /**< set A2-Korea FM Stereo */ - DRX_AUD_STANDARD_EIAJ, /**< set to Japanese FM Stereo */ - DRX_AUD_STANDARD_FM_STEREO,/**< set to FM-Stereo Radio */ - DRX_AUD_STANDARD_M_MONO, /**< for 4.5 MHz mono detected */ - DRX_AUD_STANDARD_D_K_MONO, /**< for 6.5 MHz mono detected */ - DRX_AUD_STANDARD_BG_FM, /**< set BG_FM standard */ - DRX_AUD_STANDARD_D_K1, /**< set D_K1 standard */ - DRX_AUD_STANDARD_D_K2, /**< set D_K2 standard */ - DRX_AUD_STANDARD_D_K3, /**< set D_K3 standard */ + DRX_AUD_STANDARD_BTSC, /*< set BTSC standard (USA) */ + DRX_AUD_STANDARD_A2, /*< set A2-Korea FM Stereo */ + DRX_AUD_STANDARD_EIAJ, /*< set to Japanese FM Stereo */ + DRX_AUD_STANDARD_FM_STEREO,/*< set to FM-Stereo Radio */ + DRX_AUD_STANDARD_M_MONO, /*< for 4.5 MHz mono detected */ + DRX_AUD_STANDARD_D_K_MONO, /*< for 6.5 MHz mono detected */ + DRX_AUD_STANDARD_BG_FM, /*< set BG_FM standard */ + DRX_AUD_STANDARD_D_K1, /*< set D_K1 standard */ + DRX_AUD_STANDARD_D_K2, /*< set D_K2 standard */ + DRX_AUD_STANDARD_D_K3, /*< set D_K3 standard */ DRX_AUD_STANDARD_BG_NICAM_FM, - /**< set BG_NICAM_FM standard */ + /*< set BG_NICAM_FM standard */ DRX_AUD_STANDARD_L_NICAM_AM, - /**< set L_NICAM_AM standard */ + /*< set L_NICAM_AM standard */ DRX_AUD_STANDARD_I_NICAM_FM, - /**< set I_NICAM_FM standard */ + /*< set I_NICAM_FM standard */ DRX_AUD_STANDARD_D_K_NICAM_FM, - /**< set D_K_NICAM_FM standard */ - DRX_AUD_STANDARD_NOT_READY,/**< used to detect audio standard */ + /*< set D_K_NICAM_FM standard */ + DRX_AUD_STANDARD_NOT_READY,/*< used to detect audio standard */ DRX_AUD_STANDARD_AUTO = DRX_AUTO, - /**< Automatic Standard Detection */ + /*< Automatic Standard Detection */ DRX_AUD_STANDARD_UNKNOWN = DRX_UNKNOWN - /**< used as auto and for readback */ + /*< used as auto and for readback */ }; /* CTRL_AUD_GET_STATUS - struct drx_aud_status */ -/** +/* * \enum enum drx_aud_nicam_status * \brief Status of NICAM carrier. */ enum drx_aud_nicam_status { DRX_AUD_NICAM_DETECTED = 0, - /**< NICAM carrier detected */ + /*< NICAM carrier detected */ DRX_AUD_NICAM_NOT_DETECTED, - /**< NICAM carrier not detected */ - DRX_AUD_NICAM_BAD /**< NICAM carrier bad quality */ + /*< NICAM carrier not detected */ + DRX_AUD_NICAM_BAD /*< NICAM carrier bad quality */ }; -/** +/* * \struct struct drx_aud_status * \brief Audio status characteristics. */ struct drx_aud_status { - bool stereo; /**< stereo detection */ - bool carrier_a; /**< carrier A detected */ - bool carrier_b; /**< carrier B detected */ - bool sap; /**< sap / bilingual detection */ - bool rds; /**< RDS data array present */ + bool stereo; /*< stereo detection */ + bool carrier_a; /*< carrier A detected */ + bool carrier_b; /*< carrier B detected */ + bool sap; /*< sap / bilingual detection */ + bool rds; /*< RDS data array present */ enum drx_aud_nicam_status nicam_status; - /**< status of NICAM carrier */ - s8 fm_ident; /**< FM Identification value */ + /*< status of NICAM carrier */ + s8 fm_ident; /*< FM Identification value */ }; /* CTRL_AUD_READ_RDS - DRXRDSdata_t */ -/** +/* * \struct DRXRDSdata_t * \brief Raw RDS data array. */ struct drx_cfg_aud_rds { - bool valid; /**< RDS data validation */ - u16 data[18]; /**< data from one RDS data array */ + bool valid; /*< RDS data validation */ + u16 data[18]; /*< data from one RDS data array */ }; /* DRX_CFG_AUD_VOLUME - struct drx_cfg_aud_volume - set/get */ -/** +/* * \enum DRXAudAVCDecayTime_t * \brief Automatic volume control configuration. */ enum drx_aud_avc_mode { - DRX_AUD_AVC_OFF, /**< Automatic volume control off */ - DRX_AUD_AVC_DECAYTIME_8S, /**< level volume in 8 seconds */ - DRX_AUD_AVC_DECAYTIME_4S, /**< level volume in 4 seconds */ - DRX_AUD_AVC_DECAYTIME_2S, /**< level volume in 2 seconds */ - DRX_AUD_AVC_DECAYTIME_20MS/**< level volume in 20 millisec */ + DRX_AUD_AVC_OFF, /*< Automatic volume control off */ + DRX_AUD_AVC_DECAYTIME_8S, /*< level volume in 8 seconds */ + DRX_AUD_AVC_DECAYTIME_4S, /*< level volume in 4 seconds */ + DRX_AUD_AVC_DECAYTIME_2S, /*< level volume in 2 seconds */ + DRX_AUD_AVC_DECAYTIME_20MS/*< level volume in 20 millisec */ }; -/** +/* * /enum DRXAudMaxAVCGain_t * /brief Automatic volume control max gain in audio baseband. */ enum drx_aud_avc_max_gain { - DRX_AUD_AVC_MAX_GAIN_0DB, /**< maximum AVC gain 0 dB */ - DRX_AUD_AVC_MAX_GAIN_6DB, /**< maximum AVC gain 6 dB */ - DRX_AUD_AVC_MAX_GAIN_12DB /**< maximum AVC gain 12 dB */ + DRX_AUD_AVC_MAX_GAIN_0DB, /*< maximum AVC gain 0 dB */ + DRX_AUD_AVC_MAX_GAIN_6DB, /*< maximum AVC gain 6 dB */ + DRX_AUD_AVC_MAX_GAIN_12DB /*< maximum AVC gain 12 dB */ }; -/** +/* * /enum DRXAudMaxAVCAtten_t * /brief Automatic volume control max attenuation in audio baseband. */ enum drx_aud_avc_max_atten { DRX_AUD_AVC_MAX_ATTEN_12DB, - /**< maximum AVC attenuation 12 dB */ + /*< maximum AVC attenuation 12 dB */ DRX_AUD_AVC_MAX_ATTEN_18DB, - /**< maximum AVC attenuation 18 dB */ - DRX_AUD_AVC_MAX_ATTEN_24DB/**< maximum AVC attenuation 24 dB */ + /*< maximum AVC attenuation 18 dB */ + DRX_AUD_AVC_MAX_ATTEN_24DB/*< maximum AVC attenuation 24 dB */ }; -/** +/* * \struct struct drx_cfg_aud_volume * \brief Audio volume configuration. */ struct drx_cfg_aud_volume { - bool mute; /**< mute overrides volume setting */ - s16 volume; /**< volume, range -114 to 12 dB */ - enum drx_aud_avc_mode avc_mode; /**< AVC auto volume control mode */ - u16 avc_ref_level; /**< AVC reference level */ + bool mute; /*< mute overrides volume setting */ + s16 volume; /*< volume, range -114 to 12 dB */ + enum drx_aud_avc_mode avc_mode; /*< AVC auto volume control mode */ + u16 avc_ref_level; /*< AVC reference level */ enum drx_aud_avc_max_gain avc_max_gain; - /**< AVC max gain selection */ + /*< AVC max gain selection */ enum drx_aud_avc_max_atten avc_max_atten; - /**< AVC max attenuation selection */ - s16 strength_left; /**< quasi-peak, left speaker */ - s16 strength_right; /**< quasi-peak, right speaker */ + /*< AVC max attenuation selection */ + s16 strength_left; /*< quasi-peak, left speaker */ + s16 strength_right; /*< quasi-peak, right speaker */ }; /* DRX_CFG_I2S_OUTPUT - struct drx_cfg_i2s_output - set/get */ -/** +/* * \enum enum drxi2s_mode * \brief I2S output mode. */ enum drxi2s_mode { - DRX_I2S_MODE_MASTER, /**< I2S is in master mode */ - DRX_I2S_MODE_SLAVE /**< I2S is in slave mode */ + DRX_I2S_MODE_MASTER, /*< I2S is in master mode */ + DRX_I2S_MODE_SLAVE /*< I2S is in slave mode */ }; -/** +/* * \enum enum drxi2s_word_length * \brief Width of I2S data. */ enum drxi2s_word_length { - DRX_I2S_WORDLENGTH_32 = 0,/**< I2S data is 32 bit wide */ - DRX_I2S_WORDLENGTH_16 = 1 /**< I2S data is 16 bit wide */ + DRX_I2S_WORDLENGTH_32 = 0,/*< I2S data is 32 bit wide */ + DRX_I2S_WORDLENGTH_16 = 1 /*< I2S data is 16 bit wide */ }; -/** +/* * \enum enum drxi2s_format * \brief Data wordstrobe alignment for I2S. */ enum drxi2s_format { DRX_I2S_FORMAT_WS_WITH_DATA, - /**< I2S data and wordstrobe are aligned */ + /*< I2S data and wordstrobe are aligned */ DRX_I2S_FORMAT_WS_ADVANCED - /**< I2S data one cycle after wordstrobe */ + /*< I2S data one cycle after wordstrobe */ }; -/** +/* * \enum enum drxi2s_polarity * \brief Polarity of I2S data. */ enum drxi2s_polarity { - DRX_I2S_POLARITY_RIGHT,/**< wordstrobe - right high, left low */ - DRX_I2S_POLARITY_LEFT /**< wordstrobe - right low, left high */ + DRX_I2S_POLARITY_RIGHT,/*< wordstrobe - right high, left low */ + DRX_I2S_POLARITY_LEFT /*< wordstrobe - right low, left high */ }; -/** +/* * \struct struct drx_cfg_i2s_output * \brief I2S output configuration. */ struct drx_cfg_i2s_output { - bool output_enable; /**< I2S output enable */ - u32 frequency; /**< range from 8000-48000 Hz */ - enum drxi2s_mode mode; /**< I2S mode, master or slave */ + bool output_enable; /*< I2S output enable */ + u32 frequency; /*< range from 8000-48000 Hz */ + enum drxi2s_mode mode; /*< I2S mode, master or slave */ enum drxi2s_word_length word_length; - /**< I2S wordlength, 16 or 32 bits */ - enum drxi2s_polarity polarity;/**< I2S wordstrobe polarity */ - enum drxi2s_format format; /**< I2S wordstrobe delay to data */ + /*< I2S wordlength, 16 or 32 bits */ + enum drxi2s_polarity polarity;/*< I2S wordstrobe polarity */ + enum drxi2s_format format; /*< I2S wordstrobe delay to data */ }; /* ------------------------------expert interface-----------------------------*/ -/** +/* * /enum enum drx_aud_fm_deemphasis * setting for FM-Deemphasis in audio demodulator. * */ @@ -1531,7 +1531,7 @@ struct drx_version_list { DRX_AUD_FM_DEEMPH_OFF }; -/** +/* * /enum DRXAudDeviation_t * setting for deviation mode in audio demodulator. * @@ -1541,7 +1541,7 @@ struct drx_version_list { DRX_AUD_DEVIATION_HIGH }; -/** +/* * /enum enum drx_no_carrier_option * setting for carrier, mute/noise. * */ @@ -1550,7 +1550,7 @@ struct drx_version_list { DRX_NO_CARRIER_NOISE }; -/** +/* * \enum DRXAudAutoSound_t * \brief Automatic Sound */ @@ -1560,7 +1560,7 @@ struct drx_version_list { DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_OFF }; -/** +/* * \enum DRXAudASSThres_t * \brief Automatic Sound Select Thresholds */ @@ -1570,7 +1570,7 @@ struct drx_version_list { u16 nicam; /* Nicam Threshold for ASS configuration */ }; -/** +/* * \struct struct drx_aud_carrier * \brief Carrier detection related parameters */ struct drx_aud_carrier { @@ -1580,7 +1580,7 @@ struct drx_version_list { s32 dco; /* frequency adjustment (A) */ }; -/** +/* * \struct struct drx_cfg_aud_carriers * \brief combining carrier A & B to one struct */ struct drx_cfg_aud_carriers { @@ -1588,7 +1588,7 @@ struct drx_version_list { struct drx_aud_carrier b; }; -/** +/* * /enum enum drx_aud_i2s_src * Selection of audio source */ enum drx_aud_i2s_src { @@ -1597,19 +1597,19 @@ struct drx_version_list { DRX_AUD_SRC_STEREO_OR_A, DRX_AUD_SRC_STEREO_OR_B}; -/** +/* * \enum enum drx_aud_i2s_matrix * \brief Used for selecting I2S output. */ enum drx_aud_i2s_matrix { DRX_AUD_I2S_MATRIX_A_MONO, - /**< A sound only, stereo or mono */ + /*< A sound only, stereo or mono */ DRX_AUD_I2S_MATRIX_B_MONO, - /**< B sound only, stereo or mono */ + /*< B sound only, stereo or mono */ DRX_AUD_I2S_MATRIX_STEREO, - /**< A+B sound, transparant */ - DRX_AUD_I2S_MATRIX_MONO /**< A+B mixed to mono sum, (L+R)/2 */}; + /*< A+B sound, transparant */ + DRX_AUD_I2S_MATRIX_MONO /*< A+B mixed to mono sum, (L+R)/2 */}; -/** +/* * /enum enum drx_aud_fm_matrix * setting for FM-Matrix in audio demodulator. * */ @@ -1620,7 +1620,7 @@ struct drx_version_list { DRX_AUD_FM_MATRIX_SOUND_A, DRX_AUD_FM_MATRIX_SOUND_B}; -/** +/* * \struct DRXAudMatrices_t * \brief Mixer settings */ @@ -1630,22 +1630,22 @@ struct drx_cfg_aud_mixer { enum drx_aud_fm_matrix matrix_fm; }; -/** +/* * \enum DRXI2SVidSync_t * \brief Audio/video synchronization, interacts with I2S mode. * AUTO_1 and AUTO_2 are for automatic video standard detection with preference * for NTSC or Monochrome, because the frequencies are too close (59.94 & 60 Hz) */ enum drx_cfg_aud_av_sync { - DRX_AUD_AVSYNC_OFF,/**< audio/video synchronization is off */ + DRX_AUD_AVSYNC_OFF,/*< audio/video synchronization is off */ DRX_AUD_AVSYNC_NTSC, - /**< it is an NTSC system */ + /*< it is an NTSC system */ DRX_AUD_AVSYNC_MONOCHROME, - /**< it is a MONOCHROME system */ + /*< it is a MONOCHROME system */ DRX_AUD_AVSYNC_PAL_SECAM - /**< it is a PAL/SECAM system */}; + /*< it is a PAL/SECAM system */}; -/** +/* * \struct struct drx_cfg_aud_prescale * \brief Prescalers */ struct drx_cfg_aud_prescale { @@ -1653,7 +1653,7 @@ struct drx_cfg_aud_prescale { s16 nicam_gain; }; -/** +/* * \struct struct drx_aud_beep * \brief Beep */ struct drx_aud_beep { @@ -1662,14 +1662,14 @@ struct drx_aud_beep { bool mute; }; -/** +/* * \enum enum drx_aud_btsc_detect * \brief BTSC detetcion mode */ enum drx_aud_btsc_detect { DRX_BTSC_STEREO, DRX_BTSC_MONO_AND_SAP}; -/** +/* * \struct struct drx_aud_data * \brief Audio data structure */ struct drx_aud_data { @@ -1692,7 +1692,7 @@ struct drx_aud_data { bool rds_data_present; }; -/** +/* * \enum enum drx_qam_lock_range * \brief QAM lock range mode */ enum drx_qam_lock_range { @@ -1782,7 +1782,7 @@ struct drx_aud_data { u32 wdata, /* data to write */ u32 *rdata); /* data to read */ -/** +/* * \struct struct drx_access_func * \brief Interface to an access protocol. */ struct drx_access_func { @@ -1811,85 +1811,85 @@ struct drx_reg_dump { /*============================================================================*/ /*============================================================================*/ -/** +/* * \struct struct drx_common_attr * \brief Set of common attributes, shared by all DRX devices. */ struct drx_common_attr { /* Microcode (firmware) attributes */ - char *microcode_file; /**< microcode filename */ + char *microcode_file; /*< microcode filename */ bool verify_microcode; - /**< Use microcode verify or not. */ + /*< Use microcode verify or not. */ struct drx_mc_version_rec mcversion; - /**< Version record of microcode from file */ + /*< Version record of microcode from file */ /* Clocks and tuner attributes */ s32 intermediate_freq; - /**< IF,if tuner instance not used. (kHz)*/ + /*< IF,if tuner instance not used. (kHz)*/ s32 sys_clock_freq; - /**< Systemclock frequency. (kHz) */ + /*< Systemclock frequency. (kHz) */ s32 osc_clock_freq; - /**< Oscillator clock frequency. (kHz) */ + /*< Oscillator clock frequency. (kHz) */ s16 osc_clock_deviation; - /**< Oscillator clock deviation. (ppm) */ + /*< Oscillator clock deviation. (ppm) */ bool mirror_freq_spect; - /**< Mirror IF frequency spectrum or not.*/ + /*< Mirror IF frequency spectrum or not.*/ /* Initial MPEG output attributes */ struct drx_cfg_mpeg_output mpeg_cfg; - /**< MPEG configuration */ + /*< MPEG configuration */ - bool is_opened; /**< if true instance is already opened. */ + bool is_opened; /*< if true instance is already opened. */ /* Channel scan */ struct drx_scan_param *scan_param; - /**< scan parameters */ + /*< scan parameters */ u16 scan_freq_plan_index; - /**< next index in freq plan */ + /*< next index in freq plan */ s32 scan_next_frequency; - /**< next freq to scan */ - bool scan_ready; /**< scan ready flag */ - u32 scan_max_channels;/**< number of channels in freqplan */ + /*< next freq to scan */ + bool scan_ready; /*< scan ready flag */ + u32 scan_max_channels;/*< number of channels in freqplan */ u32 scan_channels_scanned; - /**< number of channels scanned */ + /*< number of channels scanned */ /* Channel scan - inner loop: demod related */ drx_scan_func_t scan_function; - /**< function to check channel */ + /*< function to check channel */ /* Channel scan - inner loop: SYSObj related */ - void *scan_context; /**< Context Pointer of SYSObj */ + void *scan_context; /*< Context Pointer of SYSObj */ /* Channel scan - parameters for default DTV scan function in core driver */ u16 scan_demod_lock_timeout; - /**< millisecs to wait for lock */ + /*< millisecs to wait for lock */ enum drx_lock_status scan_desired_lock; - /**< lock requirement for channel found */ + /*< lock requirement for channel found */ /* scan_active can be used by SetChannel to decide how to program the tuner, fast or slow (but stable). Usually fast during scan. */ - bool scan_active; /**< true when scan routines are active */ + bool scan_active; /*< true when scan routines are active */ /* Power management */ enum drx_power_mode current_power_mode; - /**< current power management mode */ + /*< current power management mode */ /* Tuner */ - u8 tuner_port_nr; /**< nr of I2C port to wich tuner is */ + u8 tuner_port_nr; /*< nr of I2C port to wich tuner is */ s32 tuner_min_freq_rf; - /**< minimum RF input frequency, in kHz */ + /*< minimum RF input frequency, in kHz */ s32 tuner_max_freq_rf; - /**< maximum RF input frequency, in kHz */ - bool tuner_rf_agc_pol; /**< if true invert RF AGC polarity */ - bool tuner_if_agc_pol; /**< if true invert IF AGC polarity */ - bool tuner_slow_mode; /**< if true invert IF AGC polarity */ + /*< maximum RF input frequency, in kHz */ + bool tuner_rf_agc_pol; /*< if true invert RF AGC polarity */ + bool tuner_if_agc_pol; /*< if true invert IF AGC polarity */ + bool tuner_slow_mode; /*< if true invert IF AGC polarity */ struct drx_channel current_channel; - /**< current channel parameters */ + /*< current channel parameters */ enum drx_standard current_standard; - /**< current standard selection */ + /*< current standard selection */ enum drx_standard prev_standard; - /**< previous standard selection */ + /*< previous standard selection */ enum drx_standard di_cache_standard; - /**< standard in DI cache if available */ - bool use_bootloader; /**< use bootloader in open */ - u32 capabilities; /**< capabilities flags */ - u32 product_id; /**< product ID inc. metal fix number */}; + /*< standard in DI cache if available */ + bool use_bootloader; /*< use bootloader in open */ + u32 capabilities; /*< capabilities flags */ + u32 product_id; /*< product ID inc. metal fix number */}; /* * Generic functions for DRX devices. @@ -1897,16 +1897,16 @@ struct drx_reg_dump { struct drx_demod_instance; -/** +/* * \struct struct drx_demod_instance * \brief Top structure of demodulator instance. */ struct drx_demod_instance { - /**< data access protocol functions */ + /*< data access protocol functions */ struct i2c_device_addr *my_i2c_dev_addr; - /**< i2c address and device identifier */ + /*< i2c address and device identifier */ struct drx_common_attr *my_common_attr; - /**< common DRX attributes */ - void *my_ext_attr; /**< device specific attributes */ + /*< common DRX attributes */ + void *my_ext_attr; /*< device specific attributes */ /* generic demodulator data */ struct i2c_adapter *i2c; @@ -2195,7 +2195,7 @@ Conversion from enum values to human readable form. Access macros -------------------------------------------------------------------------*/ -/** +/* * \brief Create a compilable reference to the microcode attribute * \param d pointer to demod instance * @@ -2229,7 +2229,7 @@ Access macros #define DRX_ATTR_I2CDEVID(d) ((d)->my_i2c_dev_addr->i2c_dev_id) #define DRX_ISMCVERTYPE(x) ((x) == AUX_VER_RECORD) -/**************************/ +/*************************/ /* Macros with device-specific handling are converted to CFG functions */ @@ -2285,7 +2285,7 @@ Access macros #define DRX_GET_QAM_LOCKRANGE(d, x) DRX_ACCESSMACRO_GET((d), (x), \ DRX_XS_CFG_QAM_LOCKRANGE, enum drx_qam_lock_range, DRX_UNKNOWN) -/** +/* * \brief Macro to check if std is an ATV standard * \retval true std is an ATV standard * \retval false std is an ATV standard @@ -2298,7 +2298,7 @@ Access macros ((std) == DRX_STANDARD_NTSC) || \ ((std) == DRX_STANDARD_FM)) -/** +/* * \brief Macro to check if std is an QAM standard * \retval true std is an QAM standards * \retval false std is an QAM standards @@ -2308,14 +2308,14 @@ Access macros ((std) == DRX_STANDARD_ITU_C) || \ ((std) == DRX_STANDARD_ITU_D)) -/** +/* * \brief Macro to check if std is VSB standard * \retval true std is VSB standard * \retval false std is not VSB standard */ #define DRX_ISVSBSTD(std) ((std) == DRX_STANDARD_8VSB) -/** +/* * \brief Macro to check if std is DVBT standard * \retval true std is DVBT standard * \retval false std is not DVBT standard diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c index 499ccff557bf..8cbd8cc21059 100644 --- a/drivers/media/dvb-frontends/drx39xyj/drxj.c +++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c @@ -73,7 +73,7 @@ INCLUDE FILES #define DRX39XX_MAIN_FIRMWARE "dvb-fe-drxj-mc-1.0.8.fw" -/** +/* * \brief Maximum u32 value. */ #ifndef MAX_U32 @@ -100,8 +100,8 @@ INCLUDE FILES #ifndef OOB_DRX_DRIVE_STRENGTH #define OOB_DRX_DRIVE_STRENGTH 0x02 #endif -/**** START DJCOMBO patches to DRXJ registermap constants *********************/ -/**** registermap 200706071303 from drxj **************************************/ +/*** START DJCOMBO patches to DRXJ registermap constants *********************/ +/*** registermap 200706071303 from drxj **************************************/ #define ATV_TOP_CR_AMP_TH_FM 0x0 #define ATV_TOP_CR_AMP_TH_L 0xA #define ATV_TOP_CR_AMP_TH_LP 0xA @@ -188,7 +188,7 @@ INCLUDE FILES #define IQM_RC_ADJ_SEL_B_OFF 0x0 #define IQM_RC_ADJ_SEL_B_QAM 0x1 #define IQM_RC_ADJ_SEL_B_VSB 0x2 -/**** END DJCOMBO patches to DRXJ registermap *********************************/ +/*** END DJCOMBO patches to DRXJ registermap *********************************/ #include "drx_driver_version.h" @@ -208,25 +208,25 @@ DEFINES #define DRXJ_WAKE_UP_KEY (demod->my_i2c_dev_addr->i2c_addr) #endif -/** +/* * \def DRXJ_DEF_I2C_ADDR * \brief Default I2C address of a demodulator instance. */ #define DRXJ_DEF_I2C_ADDR (0x52) -/** +/* * \def DRXJ_DEF_DEMOD_DEV_ID * \brief Default device identifier of a demodultor instance. */ #define DRXJ_DEF_DEMOD_DEV_ID (1) -/** +/* * \def DRXJ_SCAN_TIMEOUT * \brief Timeout value for waiting on demod lock during channel scan (millisec). */ #define DRXJ_SCAN_TIMEOUT 1000 -/** +/* * \def HI_I2C_DELAY * \brief HI timing delay for I2C timing (in nano seconds) * @@ -234,7 +234,7 @@ DEFINES */ #define HI_I2C_DELAY 42 -/** +/* * \def HI_I2C_BRIDGE_DELAY * \brief HI timing delay for I2C timing (in nano seconds) * @@ -242,13 +242,13 @@ DEFINES */ #define HI_I2C_BRIDGE_DELAY 750 -/** +/* * \brief Time Window for MER and SER Measurement in Units of Segment duration. */ #define VSB_TOP_MEASUREMENT_PERIOD 64 #define SYMBOLS_PER_SEGMENT 832 -/** +/* * \brief bit rate and segment rate constants used for SER and BER. */ /* values taken from the QAM microcode */ @@ -260,21 +260,21 @@ DEFINES #define DRXJ_QAM_SL_SIG_POWER_QAM64 43008 #define DRXJ_QAM_SL_SIG_POWER_QAM128 20992 #define DRXJ_QAM_SL_SIG_POWER_QAM256 43520 -/** +/* * \brief Min supported symbolrates. */ #ifndef DRXJ_QAM_SYMBOLRATE_MIN #define DRXJ_QAM_SYMBOLRATE_MIN (520000) #endif -/** +/* * \brief Max supported symbolrates. */ #ifndef DRXJ_QAM_SYMBOLRATE_MAX #define DRXJ_QAM_SYMBOLRATE_MAX (7233000) #endif -/** +/* * \def DRXJ_QAM_MAX_WAITTIME * \brief Maximal wait time for QAM auto constellation in ms */ @@ -290,7 +290,7 @@ DEFINES #define DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME 200 #endif -/** +/* * \def SCU status and results * \brief SCU */ @@ -299,7 +299,7 @@ DEFINES #define FEC_RS_MEASUREMENT_PERIOD 12894 /* 1 sec */ #define FEC_RS_MEASUREMENT_PRESCALE 1 /* n sec */ -/** +/* * \def DRX_AUD_MAX_DEVIATION * \brief Needed for calculation of prescale feature in AUD */ @@ -307,14 +307,14 @@ DEFINES #define DRXJ_AUD_MAX_FM_DEVIATION 100 /* kHz */ #endif -/** +/* * \brief Needed for calculation of NICAM prescale feature in AUD */ #ifndef DRXJ_AUD_MAX_NICAM_PRESCALE #define DRXJ_AUD_MAX_NICAM_PRESCALE (9) /* dB */ #endif -/** +/* * \brief Needed for calculation of NICAM prescale feature in AUD */ #ifndef DRXJ_AUD_MAX_WAITTIME @@ -371,21 +371,21 @@ DEFINES /*============================================================================*/ /*=== GLOBAL VARIABLEs =======================================================*/ /*============================================================================*/ -/** +/* */ -/** +/* * \brief Temporary register definitions. * (register definitions that are not yet available in register master) */ -/******************************************************************************/ +/*****************************************************************************/ /* Audio block 0x103 is write only. To avoid shadowing in driver accessing */ /* RAM adresses directly. This must be READ ONLY to avoid problems. */ /* Writing to the interface adresses is more than only writing the RAM */ /* locations */ -/******************************************************************************/ -/** +/*****************************************************************************/ +/* * \brief RAM location of MODUS registers */ #define AUD_DEM_RAM_MODUS_HI__A 0x10204A3 @@ -394,13 +394,13 @@ DEFINES #define AUD_DEM_RAM_MODUS_LO__A 0x10204A4 #define AUD_DEM_RAM_MODUS_LO__M 0x0FFF -/** +/* * \brief RAM location of I2S config registers */ #define AUD_DEM_RAM_I2S_CONFIG1__A 0x10204B1 #define AUD_DEM_RAM_I2S_CONFIG2__A 0x10204B2 -/** +/* * \brief RAM location of DCO config registers */ #define AUD_DEM_RAM_DCO_B_HI__A 0x1020461 @@ -408,20 +408,20 @@ DEFINES #define AUD_DEM_RAM_DCO_A_HI__A 0x1020463 #define AUD_DEM_RAM_DCO_A_LO__A 0x1020464 -/** +/* * \brief RAM location of Threshold registers */ #define AUD_DEM_RAM_NICAM_THRSHLD__A 0x102045A #define AUD_DEM_RAM_A2_THRSHLD__A 0x10204BB #define AUD_DEM_RAM_BTSC_THRSHLD__A 0x10204A6 -/** +/* * \brief RAM location of Carrier Threshold registers */ #define AUD_DEM_RAM_CM_A_THRSHLD__A 0x10204AF #define AUD_DEM_RAM_CM_B_THRSHLD__A 0x10204B0 -/** +/* * \brief FM Matrix register fix */ #ifdef AUD_DEM_WR_FM_MATRIX__A @@ -430,7 +430,7 @@ DEFINES #define AUD_DEM_WR_FM_MATRIX__A 0x105006F /*============================================================================*/ -/** +/* * \brief Defines required for audio */ #define AUD_VOLUME_ZERO_DB 115 @@ -443,14 +443,14 @@ DEFINES #define AUD_I2S_FREQUENCY_MIN 12000UL #define AUD_RDS_ARRAY_SIZE 18 -/** +/* * \brief Needed for calculation of prescale feature in AUD */ #ifndef DRX_AUD_MAX_FM_DEVIATION #define DRX_AUD_MAX_FM_DEVIATION (100) /* kHz */ #endif -/** +/* * \brief Needed for calculation of NICAM prescale feature in AUD */ #ifndef DRX_AUD_MAX_NICAM_PRESCALE @@ -478,7 +478,7 @@ DEFINES /*=== REGISTER ACCESS MACROS =================================================*/ /*============================================================================*/ -/** +/* * This macro is used to create byte arrays for block writes. * Block writes speed up I2C traffic between host and demod. * The macro takes care of the required byte order in a 16 bits word. @@ -486,7 +486,7 @@ DEFINES */ #define DRXJ_16TO8(x) ((u8) (((u16)x) & 0xFF)), \ ((u8)((((u16)x)>>8)&0xFF)) -/** +/* * This macro is used to convert byte array to 16 bit register value for block read. * Block read speed up I2C traffic between host and demod. * The macro takes care of the required byte order in a 16 bits word. @@ -501,7 +501,7 @@ DEFINES /*=== HI COMMAND RELATED DEFINES =============================================*/ /*============================================================================*/ -/** +/* * \brief General maximum number of retries for ucode command interfaces */ #define DRXJ_MAX_RETRIES (100) @@ -807,7 +807,7 @@ static struct drxj_data drxj_data_g = { }, }; -/** +/* * \var drxj_default_addr_g * \brief Default I2C address and device identifier. */ @@ -816,7 +816,7 @@ static struct i2c_device_addr drxj_default_addr_g = { DRXJ_DEF_DEMOD_DEV_ID /* device id */ }; -/** +/* * \var drxj_default_comm_attr_g * \brief Default common attributes of a drxj demodulator instance. */ @@ -887,7 +887,7 @@ static struct drx_common_attr drxj_default_comm_attr_g = { 0 /* mfx */ }; -/** +/* * \var drxj_default_demod_g * \brief Default drxj demodulator instance. */ @@ -897,7 +897,7 @@ static struct drx_demod_instance drxj_default_demod_g = { &drxj_data_g /* demod device specific attributes */ }; -/** +/* * \brief Default audio data structure for DRK demodulator instance. * * This structure is DRXK specific. @@ -997,7 +997,7 @@ struct drxj_hi_cmd { /*=== MICROCODE RELATED STRUCTURES ===========================================*/ /*============================================================================*/ -/** +/* * struct drxu_code_block_hdr - Structure of the microcode block headers * * @addr: Destination address of the data in this block @@ -1086,7 +1086,7 @@ static u32 frac28(u32 N, u32 D) return Q1; } -/** +/* * \fn u32 log1_times100( u32 x) * \brief Compute: 100*log10(x) * \param x 32 bits @@ -1198,7 +1198,7 @@ static u32 log1_times100(u32 x) } -/** +/* * \fn u32 frac_times1e6( u16 N, u32 D) * \brief Compute: (N/D) * 1000000. * \param N nominator 16-bits. @@ -1235,7 +1235,7 @@ static u32 frac_times1e6(u32 N, u32 D) /*============================================================================*/ -/** +/* * \brief Values for NICAM prescaler gain. Computed from dB to integer * and rounded. For calc used formula: 16*10^(prescaleGain[dB]/20). * @@ -1280,7 +1280,7 @@ static const u16 nicam_presc_table_val[43] = { #define DRXJ_DAP_AUDTRIF_TIMEOUT 80 /* millisec */ /*============================================================================*/ -/** +/* * \fn bool is_handled_by_aud_tr_if( u32 addr ) * \brief Check if this address is handled by the audio token ring interface. * \param addr @@ -1386,7 +1386,7 @@ int drxbsp_i2c_write_read(struct i2c_device_addr *w_dev_addr, /*============================================================================*/ -/****************************** +/***************************** * * int drxdap_fasi_read_block ( * struct i2c_device_addr *dev_addr, -- address of I2C device @@ -1498,7 +1498,7 @@ static int drxdap_fasi_read_block(struct i2c_device_addr *dev_addr, } -/****************************** +/***************************** * * int drxdap_fasi_read_reg16 ( * struct i2c_device_addr *dev_addr, -- address of I2C device @@ -1531,7 +1531,7 @@ static int drxdap_fasi_read_reg16(struct i2c_device_addr *dev_addr, return rc; } -/****************************** +/***************************** * * int drxdap_fasi_read_reg32 ( * struct i2c_device_addr *dev_addr, -- address of I2C device @@ -1566,7 +1566,7 @@ static int drxdap_fasi_read_reg32(struct i2c_device_addr *dev_addr, return rc; } -/****************************** +/***************************** * * int drxdap_fasi_write_block ( * struct i2c_device_addr *dev_addr, -- address of I2C device @@ -1705,7 +1705,7 @@ static int drxdap_fasi_write_block(struct i2c_device_addr *dev_addr, return first_err; } -/****************************** +/***************************** * * int drxdap_fasi_write_reg16 ( * struct i2c_device_addr *dev_addr, -- address of I2C device @@ -1734,7 +1734,7 @@ static int drxdap_fasi_write_reg16(struct i2c_device_addr *dev_addr, return drxdap_fasi_write_block(dev_addr, addr, sizeof(data), buf, flags); } -/****************************** +/***************************** * * int drxdap_fasi_read_modify_write_reg16 ( * struct i2c_device_addr *dev_addr, -- address of I2C device @@ -1778,7 +1778,7 @@ static int drxdap_fasi_read_modify_write_reg16(struct i2c_device_addr *dev_addr, return rc; } -/****************************** +/***************************** * * int drxdap_fasi_write_reg32 ( * struct i2c_device_addr *dev_addr, -- address of I2C device @@ -1811,7 +1811,7 @@ static int drxdap_fasi_write_reg32(struct i2c_device_addr *dev_addr, /*============================================================================*/ -/** +/* * \fn int drxj_dap_rm_write_reg16short * \brief Read modify write 16 bits audio register using short format only. * \param dev_addr @@ -1890,7 +1890,7 @@ static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr, /*============================================================================*/ -/** +/* * \fn int drxj_dap_read_aud_reg16 * \brief Read 16 bits audio register * \param dev_addr @@ -1997,7 +1997,7 @@ static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr, } /*============================================================================*/ -/** +/* * \fn int drxj_dap_write_aud_reg16 * \brief Write 16 bits audio register * \param dev_addr @@ -2086,7 +2086,7 @@ static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr, #define DRXJ_HI_ATOMIC_READ SIO_HI_RA_RAM_PAR_3_ACP_RW_READ #define DRXJ_HI_ATOMIC_WRITE SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE -/** +/* * \fn int drxj_dap_atomic_read_write_block() * \brief Basic access routine for atomic read or write access * \param dev_addr pointer to i2c dev address @@ -2168,7 +2168,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int drxj_dap_atomic_read_reg32() * \brief Atomic read of 32 bits words */ @@ -2215,7 +2215,7 @@ int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr, /*============================================================================*/ /*============================================================================*/ -/** +/* * \fn int hi_cfg_command() * \brief Configure HI with settings stored in the demod structure. * \param demod Demodulator. @@ -2258,7 +2258,7 @@ rw_error: return rc; } -/** +/* * \fn int hi_command() * \brief Configure HI with settings stored in the demod structure. * \param dev_addr I2C address. @@ -2369,7 +2369,7 @@ rw_error: return rc; } -/** +/* * \fn int init_hi( const struct drx_demod_instance *demod ) * \brief Initialise and configurate HI. * \param demod pointer to demod data. @@ -2450,7 +2450,7 @@ rw_error: /*============================================================================*/ /*============================================================================*/ -/** +/* * \fn int get_device_capabilities() * \brief Get and store device capabilities. * \param demod Pointer to demodulator instance. @@ -2656,7 +2656,7 @@ rw_error: return rc; } -/** +/* * \fn int power_up_device() * \brief Power up device. * \param demod Pointer to demodulator instance. @@ -2710,7 +2710,7 @@ static int power_up_device(struct drx_demod_instance *demod) /*----------------------------------------------------------------------------*/ /* MPEG Output Configuration Functions - begin */ /*----------------------------------------------------------------------------*/ -/** +/* * \fn int ctrl_set_cfg_mpeg_output() * \brief Set MPEG output configuration of the device. * \param devmod Pointer to demodulator instance. @@ -3356,7 +3356,7 @@ rw_error: /* miscellaneous configurations - begin */ /*----------------------------------------------------------------------------*/ -/** +/* * \fn int set_mpegtei_handling() * \brief Activate MPEG TEI handling settings. * \param devmod Pointer to demodulator instance. @@ -3429,7 +3429,7 @@ rw_error: } /*----------------------------------------------------------------------------*/ -/** +/* * \fn int bit_reverse_mpeg_output() * \brief Set MPEG output bit-endian settings. * \param devmod Pointer to demodulator instance. @@ -3472,7 +3472,7 @@ rw_error: } /*----------------------------------------------------------------------------*/ -/** +/* * \fn int set_mpeg_start_width() * \brief Set MPEG start width. * \param devmod Pointer to demodulator instance. @@ -3522,7 +3522,7 @@ rw_error: /*----------------------------------------------------------------------------*/ /* UIO Configuration Functions - begin */ /*----------------------------------------------------------------------------*/ -/** +/* * \fn int ctrl_set_uio_cfg() * \brief Configure modus oprandi UIO. * \param demod Pointer to demodulator instance. @@ -3659,7 +3659,7 @@ rw_error: return rc; } -/** +/* * \fn int ctrl_uio_write() * \brief Write to a UIO. * \param demod Pointer to demodulator instance. @@ -3868,7 +3868,7 @@ rw_error: /*----------------------------------------------------------------------------*/ /* I2C Bridge Functions - begin */ /*----------------------------------------------------------------------------*/ -/** +/* * \fn int ctrl_i2c_bridge() * \brief Open or close the I2C switch to tuner. * \param demod Pointer to demodulator instance. @@ -3903,7 +3903,7 @@ ctrl_i2c_bridge(struct drx_demod_instance *demod, bool *bridge_closed) /*----------------------------------------------------------------------------*/ /* Smart antenna Functions - begin */ /*----------------------------------------------------------------------------*/ -/** +/* * \fn int smart_ant_init() * \brief Initialize Smart Antenna. * \param pointer to struct drx_demod_instance. @@ -4116,7 +4116,7 @@ rw_error: return rc; } -/** +/* * \fn int DRXJ_DAP_SCUAtomicReadWriteBlock() * \brief Basic access routine for SCU atomic read or write access * \param dev_addr pointer to i2c dev address @@ -4188,7 +4188,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int DRXJ_DAP_AtomicReadReg16() * \brief Atomic read of 16 bits words */ @@ -4216,7 +4216,7 @@ int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr, } /*============================================================================*/ -/** +/* * \fn int drxj_dap_scu_atomic_write_reg16() * \brief Atomic read of 16 bits words */ @@ -4237,7 +4237,7 @@ int drxj_dap_scu_atomic_write_reg16(struct i2c_device_addr *dev_addr, } /* -------------------------------------------------------------------------- */ -/** +/* * \brief Measure result of ADC synchronisation * \param demod demod instance * \param count (returned) count @@ -4297,7 +4297,7 @@ rw_error: return rc; } -/** +/* * \brief Synchronize analog and digital clock domains * \param demod demod instance * \return int. @@ -4365,7 +4365,7 @@ rw_error: /*== 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/ /*============================================================================*/ /*============================================================================*/ -/** +/* * \fn int init_agc () * \brief Initialize AGC for all standards. * \param demod instance of demodulator. @@ -4741,7 +4741,7 @@ rw_error: return rc; } -/** +/* * \fn int set_frequency () * \brief Set frequency shift. * \param demod instance of demodulator. @@ -4839,7 +4839,7 @@ rw_error: return rc; } -/** +/* * \fn int get_acc_pkt_err() * \brief Retrieve signal strength for VSB and QAM. * \param demod Pointer to demod instance @@ -4891,7 +4891,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int set_agc_rf () * \brief Configure RF AGC * \param demod instance of demodulator. @@ -5105,7 +5105,7 @@ rw_error: return rc; } -/** +/* * \fn int set_agc_if () * \brief Configure If AGC * \param demod instance of demodulator. @@ -5334,7 +5334,7 @@ rw_error: return rc; } -/** +/* * \fn int set_iqm_af () * \brief Configure IQM AF registers * \param demod instance of demodulator. @@ -5380,7 +5380,7 @@ rw_error: /*============================================================================*/ /*============================================================================*/ -/** +/* * \fn int power_down_vsb () * \brief Powr down QAM related blocks. * \param demod instance of demodulator. @@ -5478,7 +5478,7 @@ rw_error: return rc; } -/** +/* * \fn int set_vsb_leak_n_gain () * \brief Set ATSC demod. * \param demod instance of demodulator. @@ -5694,7 +5694,7 @@ rw_error: return rc; } -/** +/* * \fn int set_vsb() * \brief Set 8VSB demod. * \param demod instance of demodulator. @@ -6200,7 +6200,7 @@ rw_error: return rc; } -/** +/* * \fn static short get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr, u16 *PckErrs) * \brief Get the values of packet error in 8VSB mode * \return Error code @@ -6239,7 +6239,7 @@ rw_error: return rc; } -/** +/* * \fn static short GetVSBBer(struct i2c_device_addr *dev_addr, u32 *ber) * \brief Get the values of ber in VSB mode * \return Error code @@ -6284,7 +6284,7 @@ rw_error: return rc; } -/** +/* * \fn static short get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber) * \brief Get the values of ber in VSB mode * \return Error code @@ -6306,7 +6306,7 @@ static int get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, return 0; } -/** +/* * \fn static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer) * \brief Get the values of MER * \return Error code @@ -6340,7 +6340,7 @@ rw_error: /*============================================================================*/ /*============================================================================*/ -/** +/* * \fn int power_down_qam () * \brief Powr down QAM related blocks. * \param demod instance of demodulator. @@ -6444,7 +6444,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int set_qam_measurement () * \brief Setup of the QAM Measuremnt intervals for signal quality * \param demod instance of demod. @@ -6656,7 +6656,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int set_qam16 () * \brief QAM16 specific setup * \param demod instance of demod. @@ -6891,7 +6891,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int set_qam32 () * \brief QAM32 specific setup * \param demod instance of demod. @@ -7126,7 +7126,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int set_qam64 () * \brief QAM64 specific setup * \param demod instance of demod. @@ -7362,7 +7362,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int set_qam128 () * \brief QAM128 specific setup * \param demod: instance of demod. @@ -7597,7 +7597,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int set_qam256 () * \brief QAM256 specific setup * \param demod: instance of demod. @@ -7835,7 +7835,7 @@ rw_error: #define QAM_SET_OP_CONSTELLATION 0x2 #define QAM_SET_OP_SPECTRUM 0X4 -/** +/* * \fn int set_qam () * \brief Set QAM demod. * \param demod: instance of demod. @@ -8845,7 +8845,7 @@ rw_error: #define DEMOD_LOCKED 0x1 #define SYNC_FLIPPED 0x2 #define SPEC_MIRRORED 0x4 -/** +/* * \fn int qam64auto () * \brief auto do sync pattern switching and mirroring. * \param demod: instance of demod. @@ -8993,7 +8993,7 @@ rw_error: return rc; } -/** +/* * \fn int qam256auto () * \brief auto do sync pattern switching and mirroring. * \param demod: instance of demod. @@ -9077,7 +9077,7 @@ rw_error: return rc; } -/** +/* * \fn int set_qam_channel () * \brief Set QAM channel according to the requested constellation. * \param demod: instance of demod. @@ -9284,7 +9284,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn static short get_qamrs_err_count(struct i2c_device_addr *dev_addr) * \brief Get RS error count in QAM mode (used for post RS BER calculation) * \return Error code @@ -9355,7 +9355,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int get_sig_strength() * \brief Retrieve signal strength for VSB and QAM. * \param demod Pointer to demod instance @@ -9435,7 +9435,7 @@ rw_error: return rc; } -/** +/* * \fn int ctrl_get_qam_sig_quality() * \brief Retrieve QAM signal quality from device. * \param devmod Pointer to demodulator instance. @@ -9721,7 +9721,7 @@ rw_error: */ /* -------------------------------------------------------------------------- */ -/** +/* * \fn int power_down_atv () * \brief Power down ATV. * \param demod instance of demodulator @@ -9822,7 +9822,7 @@ rw_error: /*============================================================================*/ -/** +/* * \brief Power up AUD. * \param demod instance of demodulator * \return int. @@ -9850,7 +9850,7 @@ rw_error: return rc; } -/** +/* * \fn int set_orx_nsu_aox() * \brief Configure OrxNsuAox for OOB * \param demod instance of demodulator. @@ -9884,7 +9884,7 @@ rw_error: return rc; } -/** +/* * \fn int ctrl_set_oob() * \brief Set OOB channel to be used. * \param demod instance of demodulator @@ -9986,9 +9986,9 @@ static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_par 20; } - /*********/ + /********/ /* Stop */ - /*********/ + /********/ rc = drxj_dap_write_reg16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP, 0); if (rc != 0) { pr_err("error %d\n", rc); @@ -10004,9 +10004,9 @@ static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_par pr_err("error %d\n", rc); goto rw_error; } - /*********/ + /********/ /* Reset */ - /*********/ + /********/ scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB | SCU_RAM_COMMAND_CMD_DEMOD_RESET; scu_cmd.parameter_len = 0; @@ -10017,9 +10017,9 @@ static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_par pr_err("error %d\n", rc); goto rw_error; } - /***********/ + /**********/ /* SET_ENV */ - /***********/ + /**********/ /* set frequency, spectrum inversion and data rate */ scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV; @@ -10376,9 +10376,9 @@ static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_par pr_err("error %d\n", rc); goto rw_error; } - /*********/ + /********/ /* Start */ - /*********/ + /********/ scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB | SCU_RAM_COMMAND_CMD_DEMOD_START; scu_cmd.parameter_len = 0; @@ -10419,7 +10419,7 @@ rw_error: /*============================================================================= ===== ctrl_set_channel() ========================================================== ===========================================================================*/ -/** +/* * \fn int ctrl_set_channel() * \brief Select a new transmission channel. * \param demod instance of demod. @@ -10652,7 +10652,7 @@ rw_error: ===== SigQuality() ========================================================== ===========================================================================*/ -/** +/* * \fn int ctrl_sig_quality() * \brief Retrieve signal quality form device. * \param devmod Pointer to demodulator instance. @@ -10768,7 +10768,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int ctrl_lock_status() * \brief Retrieve lock status . * \param dev_addr Pointer to demodulator device address. @@ -10856,7 +10856,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int ctrl_set_standard() * \brief Set modulation standard to be used. * \param standard Modulation standard. @@ -11012,7 +11012,7 @@ static void drxj_reset_mode(struct drxj_data *ext_attr) ext_attr->vsb_pre_saw_cfg.use_pre_saw = true; } -/** +/* * \fn int ctrl_power_mode() * \brief Set the power mode of the device to the specified power mode * \param demod Pointer to demodulator instance. @@ -11171,7 +11171,7 @@ rw_error: /*== CTRL Set/Get Config related functions ===================================*/ /*============================================================================*/ -/** +/* * \fn int ctrl_set_cfg_pre_saw() * \brief Set Pre-saw reference. * \param demod demod instance @@ -11234,7 +11234,7 @@ rw_error: /*============================================================================*/ -/** +/* * \fn int ctrl_set_cfg_afe_gain() * \brief Set AFE Gain. * \param demod demod instance @@ -11324,7 +11324,7 @@ static int drx_ctrl_u_code(struct drx_demod_instance *demod, enum drxu_code_action action); static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state); -/** +/* * \fn drxj_open() * \brief Open the demod instance, configure device, configure drxdriver * \return Status_t Return status. @@ -11543,7 +11543,7 @@ rw_error: } /*============================================================================*/ -/** +/* * \fn drxj_close() * \brief Close the demod instance, power down the device * \return Status_t Return status. @@ -11594,7 +11594,7 @@ rw_error: * Microcode related functions */ -/** +/* * drx_u_code_compute_crc - Compute CRC of block of microcode data. * @block_data: Pointer to microcode data. * @nr_words: Size of microcode block (number of 16 bits words). @@ -11622,7 +11622,7 @@ static u16 drx_u_code_compute_crc(u8 *block_data, u16 nr_words) return (u16)(crc_word >> 16); } -/** +/* * drx_check_firmware - checks if the loaded firmware is valid * * @demod: demod structure @@ -11708,7 +11708,7 @@ eof: return -EINVAL; } -/** +/* * drx_ctrl_u_code - Handle microcode upload or verify. * @dev_addr: Address of device. * @mc_info: Pointer to information about microcode data. diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.h b/drivers/media/dvb-frontends/drx39xyj/drxj.h index 6c5b8f78f9f6..d3ee1c23bb2f 100644 --- a/drivers/media/dvb-frontends/drx39xyj/drxj.h +++ b/drivers/media/dvb-frontends/drx39xyj/drxj.h @@ -69,15 +69,15 @@ TYPEDEFS struct drxjscu_cmd { u16 command; - /**< Command number */ + /*< Command number */ u16 parameter_len; - /**< Data length in byte */ + /*< Data length in byte */ u16 result_len; - /**< result length in byte */ + /*< result length in byte */ u16 *parameter; - /**< General purpous param */ + /*< General purpous param */ u16 *result; - /**< General purpous param */}; + /*< General purpous param */}; /*============================================================================*/ /*============================================================================*/ @@ -130,7 +130,7 @@ TYPEDEFS DRXJ_CFG_MAX /* dummy, never to be used */}; -/** +/* * /struct enum drxj_cfg_smart_ant_io * smart antenna i/o. */ enum drxj_cfg_smart_ant_io { @@ -138,7 +138,7 @@ enum drxj_cfg_smart_ant_io { DRXJ_SMT_ANT_INPUT }; -/** +/* * /struct struct drxj_cfg_smart_ant * Set smart antenna. */ struct drxj_cfg_smart_ant { @@ -146,7 +146,7 @@ enum drxj_cfg_smart_ant_io { u16 ctrl_data; }; -/** +/* * /struct DRXJAGCSTATUS_t * AGC status information from the DRXJ-IQM-AF. */ @@ -158,7 +158,7 @@ struct drxj_agc_status { /* DRXJ_CFG_AGC_RF, DRXJ_CFG_AGC_IF */ -/** +/* * /struct enum drxj_agc_ctrl_mode * Available AGCs modes in the DRXJ. */ enum drxj_agc_ctrl_mode { @@ -166,7 +166,7 @@ struct drxj_agc_status { DRX_AGC_CTRL_USER, DRX_AGC_CTRL_OFF}; -/** +/* * /struct struct drxj_cfg_agc * Generic interface for all AGCs present on the DRXJ. */ struct drxj_cfg_agc { @@ -182,7 +182,7 @@ struct drxj_agc_status { /* DRXJ_CFG_PRE_SAW */ -/** +/* * /struct struct drxj_cfg_pre_saw * Interface to configure pre SAW sense. */ struct drxj_cfg_pre_saw { @@ -192,14 +192,14 @@ struct drxj_agc_status { /* DRXJ_CFG_AFE_GAIN */ -/** +/* * /struct struct drxj_cfg_afe_gain * Interface to configure gain of AFE (LNA + PGA). */ struct drxj_cfg_afe_gain { enum drx_standard standard; /* standard to which these settings apply */ u16 gain; /* gain in 0.1 dB steps, DRXJ range 140 .. 335 */}; -/** +/* * /struct drxjrs_errors * Available failure information in DRXJ_FEC_RS. * @@ -208,25 +208,25 @@ struct drxj_agc_status { */ struct drxjrs_errors { u16 nr_bit_errors; - /**< no of pre RS bit errors */ + /*< no of pre RS bit errors */ u16 nr_symbol_errors; - /**< no of pre RS symbol errors */ + /*< no of pre RS symbol errors */ u16 nr_packet_errors; - /**< no of pre RS packet errors */ + /*< no of pre RS packet errors */ u16 nr_failures; - /**< no of post RS failures to decode */ + /*< no of post RS failures to decode */ u16 nr_snc_par_fail_count; - /**< no of post RS bit erros */ + /*< no of post RS bit erros */ }; -/** +/* * /struct struct drxj_cfg_vsb_misc * symbol error rate */ struct drxj_cfg_vsb_misc { u32 symb_error; - /**< symbol error rate sps */}; + /*< symbol error rate sps */}; -/** +/* * /enum enum drxj_mpeg_output_clock_rate * Mpeg output clock rate. * */ @@ -234,7 +234,7 @@ struct drxj_agc_status { DRXJ_MPEG_START_WIDTH_1CLKCYC, DRXJ_MPEG_START_WIDTH_8CLKCYC}; -/** +/* * /enum enum drxj_mpeg_output_clock_rate * Mpeg output clock rate. * */ @@ -247,20 +247,20 @@ struct drxj_agc_status { DRXJ_MPEGOUTPUT_CLOCK_RATE_25313K, DRXJ_MPEGOUTPUT_CLOCK_RATE_21696K}; -/** +/* * /struct DRXJCfgMisc_t * Change TEI bit of MPEG output * reverse MPEG output bit order * set MPEG output clock rate */ struct drxj_cfg_mpeg_output_misc { - bool disable_tei_handling; /**< if true pass (not change) TEI bit */ - bool bit_reverse_mpeg_outout; /**< if true, parallel: msb on MD0; serial: lsb out first */ + bool disable_tei_handling; /*< if true pass (not change) TEI bit */ + bool bit_reverse_mpeg_outout; /*< if true, parallel: msb on MD0; serial: lsb out first */ enum drxj_mpeg_output_clock_rate mpeg_output_clock_rate; - /**< set MPEG output clock rate that overwirtes the derived one from symbol rate */ - enum drxj_mpeg_start_width mpeg_start_width; /**< set MPEG output start width */}; + /*< set MPEG output clock rate that overwirtes the derived one from symbol rate */ + enum drxj_mpeg_start_width mpeg_start_width; /*< set MPEG output start width */}; -/** +/* * /enum enum drxj_xtal_freq * Supported external crystal reference frequency. */ enum drxj_xtal_freq { @@ -269,21 +269,21 @@ struct drxj_agc_status { DRXJ_XTAL_FREQ_20P25MHZ, DRXJ_XTAL_FREQ_4MHZ}; -/** +/* * /enum enum drxj_xtal_freq * Supported external crystal reference frequency. */ enum drxji2c_speed { DRXJ_I2C_SPEED_400KBPS, DRXJ_I2C_SPEED_100KBPS}; -/** +/* * /struct struct drxj_cfg_hw_cfg * Get hw configuration, such as crystal reference frequency, I2C speed, etc... */ struct drxj_cfg_hw_cfg { enum drxj_xtal_freq xtal_freq; - /**< crystal reference frequency */ + /*< crystal reference frequency */ enum drxji2c_speed i2c_speed; - /**< 100 or 400 kbps */}; + /*< 100 or 400 kbps */}; /* * DRXJ_CFG_ATV_MISC @@ -352,7 +352,7 @@ struct drxj_cfg_oob_misc { * DRXJ_CFG_ATV_OUTPUT */ -/** +/* * /enum DRXJAttenuation_t * Attenuation setting for SIF AGC. * @@ -363,7 +363,7 @@ struct drxj_cfg_oob_misc { DRXJ_SIF_ATTENUATION_6DB, DRXJ_SIF_ATTENUATION_9DB}; -/** +/* * /struct struct drxj_cfg_atv_output * SIF attenuation setting. * */ @@ -398,7 +398,7 @@ struct drxj_cfg_atv_output { /*============================================================================*/ /*========================================*/ -/** +/* * /struct struct drxj_data * DRXJ specific attributes. * * Global data container for DRXJ specific data. @@ -406,93 +406,93 @@ struct drxj_cfg_atv_output { */ struct drxj_data { /* device capabilties (determined during drx_open()) */ - bool has_lna; /**< true if LNA (aka PGA) present */ - bool has_oob; /**< true if OOB supported */ - bool has_ntsc; /**< true if NTSC supported */ - bool has_btsc; /**< true if BTSC supported */ - bool has_smatx; /**< true if mat_tx is available */ - bool has_smarx; /**< true if mat_rx is available */ - bool has_gpio; /**< true if GPIO is available */ - bool has_irqn; /**< true if IRQN is available */ + bool has_lna; /*< true if LNA (aka PGA) present */ + bool has_oob; /*< true if OOB supported */ + bool has_ntsc; /*< true if NTSC supported */ + bool has_btsc; /*< true if BTSC supported */ + bool has_smatx; /*< true if mat_tx is available */ + bool has_smarx; /*< true if mat_rx is available */ + bool has_gpio; /*< true if GPIO is available */ + bool has_irqn; /*< true if IRQN is available */ /* A1/A2/A... */ - u8 mfx; /**< metal fix */ + u8 mfx; /*< metal fix */ /* tuner settings */ - bool mirror_freq_spect_oob;/**< tuner inversion (true = tuner mirrors the signal */ + bool mirror_freq_spect_oob;/*< tuner inversion (true = tuner mirrors the signal */ /* standard/channel settings */ - enum drx_standard standard; /**< current standard information */ + enum drx_standard standard; /*< current standard information */ enum drx_modulation constellation; - /**< current constellation */ - s32 frequency; /**< center signal frequency in KHz */ + /*< current constellation */ + s32 frequency; /*< center signal frequency in KHz */ enum drx_bandwidth curr_bandwidth; - /**< current channel bandwidth */ - enum drx_mirror mirror; /**< current channel mirror */ + /*< current channel bandwidth */ + enum drx_mirror mirror; /*< current channel mirror */ /* signal quality information */ - u32 fec_bits_desired; /**< BER accounting period */ - u16 fec_vd_plen; /**< no of trellis symbols: VD SER measurement period */ - u16 qam_vd_prescale; /**< Viterbi Measurement Prescale */ - u16 qam_vd_period; /**< Viterbi Measurement period */ - u16 fec_rs_plen; /**< defines RS BER measurement period */ - u16 fec_rs_prescale; /**< ReedSolomon Measurement Prescale */ - u16 fec_rs_period; /**< ReedSolomon Measurement period */ - bool reset_pkt_err_acc; /**< Set a flag to reset accumulated packet error */ - u16 pkt_err_acc_start; /**< Set a flag to reset accumulated packet error */ + u32 fec_bits_desired; /*< BER accounting period */ + u16 fec_vd_plen; /*< no of trellis symbols: VD SER measurement period */ + u16 qam_vd_prescale; /*< Viterbi Measurement Prescale */ + u16 qam_vd_period; /*< Viterbi Measurement period */ + u16 fec_rs_plen; /*< defines RS BER measurement period */ + u16 fec_rs_prescale; /*< ReedSolomon Measurement Prescale */ + u16 fec_rs_period; /*< ReedSolomon Measurement period */ + bool reset_pkt_err_acc; /*< Set a flag to reset accumulated packet error */ + u16 pkt_err_acc_start; /*< Set a flag to reset accumulated packet error */ /* HI configuration */ - u16 hi_cfg_timing_div; /**< HI Configure() parameter 2 */ - u16 hi_cfg_bridge_delay; /**< HI Configure() parameter 3 */ - u16 hi_cfg_wake_up_key; /**< HI Configure() parameter 4 */ - u16 hi_cfg_ctrl; /**< HI Configure() parameter 5 */ - u16 hi_cfg_transmit; /**< HI Configure() parameter 6 */ + u16 hi_cfg_timing_div; /*< HI Configure() parameter 2 */ + u16 hi_cfg_bridge_delay; /*< HI Configure() parameter 3 */ + u16 hi_cfg_wake_up_key; /*< HI Configure() parameter 4 */ + u16 hi_cfg_ctrl; /*< HI Configure() parameter 5 */ + u16 hi_cfg_transmit; /*< HI Configure() parameter 6 */ /* UIO configuration */ - enum drxuio_mode uio_sma_rx_mode;/**< current mode of SmaRx pin */ - enum drxuio_mode uio_sma_tx_mode;/**< current mode of SmaTx pin */ - enum drxuio_mode uio_gpio_mode; /**< current mode of ASEL pin */ - enum drxuio_mode uio_irqn_mode; /**< current mode of IRQN pin */ + enum drxuio_mode uio_sma_rx_mode;/*< current mode of SmaRx pin */ + enum drxuio_mode uio_sma_tx_mode;/*< current mode of SmaTx pin */ + enum drxuio_mode uio_gpio_mode; /*< current mode of ASEL pin */ + enum drxuio_mode uio_irqn_mode; /*< current mode of IRQN pin */ /* IQM fs frequecy shift and inversion */ - u32 iqm_fs_rate_ofs; /**< frequency shifter setting after setchannel */ - bool pos_image; /**< Ture: positive image */ + u32 iqm_fs_rate_ofs; /*< frequency shifter setting after setchannel */ + bool pos_image; /*< Ture: positive image */ /* IQM RC frequecy shift */ - u32 iqm_rc_rate_ofs; /**< frequency shifter setting after setchannel */ + u32 iqm_rc_rate_ofs; /*< frequency shifter setting after setchannel */ /* ATV configuration */ - u32 atv_cfg_changed_flags; /**< flag: flags cfg changes */ - s16 atv_top_equ0[DRXJ_COEF_IDX_MAX]; /**< shadow of ATV_TOP_EQU0__A */ - s16 atv_top_equ1[DRXJ_COEF_IDX_MAX]; /**< shadow of ATV_TOP_EQU1__A */ - s16 atv_top_equ2[DRXJ_COEF_IDX_MAX]; /**< shadow of ATV_TOP_EQU2__A */ - s16 atv_top_equ3[DRXJ_COEF_IDX_MAX]; /**< shadow of ATV_TOP_EQU3__A */ - bool phase_correction_bypass;/**< flag: true=bypass */ - s16 atv_top_vid_peak; /**< shadow of ATV_TOP_VID_PEAK__A */ - u16 atv_top_noise_th; /**< shadow of ATV_TOP_NOISE_TH__A */ - bool enable_cvbs_output; /**< flag CVBS ouput enable */ - bool enable_sif_output; /**< flag SIF ouput enable */ + u32 atv_cfg_changed_flags; /*< flag: flags cfg changes */ + s16 atv_top_equ0[DRXJ_COEF_IDX_MAX]; /*< shadow of ATV_TOP_EQU0__A */ + s16 atv_top_equ1[DRXJ_COEF_IDX_MAX]; /*< shadow of ATV_TOP_EQU1__A */ + s16 atv_top_equ2[DRXJ_COEF_IDX_MAX]; /*< shadow of ATV_TOP_EQU2__A */ + s16 atv_top_equ3[DRXJ_COEF_IDX_MAX]; /*< shadow of ATV_TOP_EQU3__A */ + bool phase_correction_bypass;/*< flag: true=bypass */ + s16 atv_top_vid_peak; /*< shadow of ATV_TOP_VID_PEAK__A */ + u16 atv_top_noise_th; /*< shadow of ATV_TOP_NOISE_TH__A */ + bool enable_cvbs_output; /*< flag CVBS ouput enable */ + bool enable_sif_output; /*< flag SIF ouput enable */ enum drxjsif_attenuation sif_attenuation; - /**< current SIF att setting */ + /*< current SIF att setting */ /* Agc configuration for QAM and VSB */ - struct drxj_cfg_agc qam_rf_agc_cfg; /**< qam RF AGC config */ - struct drxj_cfg_agc qam_if_agc_cfg; /**< qam IF AGC config */ - struct drxj_cfg_agc vsb_rf_agc_cfg; /**< vsb RF AGC config */ - struct drxj_cfg_agc vsb_if_agc_cfg; /**< vsb IF AGC config */ + struct drxj_cfg_agc qam_rf_agc_cfg; /*< qam RF AGC config */ + struct drxj_cfg_agc qam_if_agc_cfg; /*< qam IF AGC config */ + struct drxj_cfg_agc vsb_rf_agc_cfg; /*< vsb RF AGC config */ + struct drxj_cfg_agc vsb_if_agc_cfg; /*< vsb IF AGC config */ /* PGA gain configuration for QAM and VSB */ - u16 qam_pga_cfg; /**< qam PGA config */ - u16 vsb_pga_cfg; /**< vsb PGA config */ + u16 qam_pga_cfg; /*< qam PGA config */ + u16 vsb_pga_cfg; /*< vsb PGA config */ /* Pre SAW configuration for QAM and VSB */ struct drxj_cfg_pre_saw qam_pre_saw_cfg; - /**< qam pre SAW config */ + /*< qam pre SAW config */ struct drxj_cfg_pre_saw vsb_pre_saw_cfg; - /**< qam pre SAW config */ + /*< qam pre SAW config */ /* Version information */ - char v_text[2][12]; /**< allocated text versions */ - struct drx_version v_version[2]; /**< allocated versions structs */ + char v_text[2][12]; /*< allocated text versions */ + struct drx_version v_version[2]; /*< allocated versions structs */ struct drx_version_list v_list_elements[2]; - /**< allocated version list */ + /*< allocated version list */ /* smart antenna configuration */ bool smart_ant_inverted; @@ -502,25 +502,25 @@ struct drxj_cfg_atv_output { bool oob_power_on; /* MPEG static bitrate setting */ - u32 mpeg_ts_static_bitrate; /**< bitrate static MPEG output */ - bool disable_te_ihandling; /**< MPEG TS TEI handling */ - bool bit_reverse_mpeg_outout;/**< MPEG output bit order */ + u32 mpeg_ts_static_bitrate; /*< bitrate static MPEG output */ + bool disable_te_ihandling; /*< MPEG TS TEI handling */ + bool bit_reverse_mpeg_outout;/*< MPEG output bit order */ enum drxj_mpeg_output_clock_rate mpeg_output_clock_rate; - /**< MPEG output clock rate */ + /*< MPEG output clock rate */ enum drxj_mpeg_start_width mpeg_start_width; - /**< MPEG Start width */ + /*< MPEG Start width */ /* Pre SAW & Agc configuration for ATV */ struct drxj_cfg_pre_saw atv_pre_saw_cfg; - /**< atv pre SAW config */ - struct drxj_cfg_agc atv_rf_agc_cfg; /**< atv RF AGC config */ - struct drxj_cfg_agc atv_if_agc_cfg; /**< atv IF AGC config */ - u16 atv_pga_cfg; /**< atv pga config */ + /*< atv pre SAW config */ + struct drxj_cfg_agc atv_rf_agc_cfg; /*< atv RF AGC config */ + struct drxj_cfg_agc atv_if_agc_cfg; /*< atv IF AGC config */ + u16 atv_pga_cfg; /*< atv pga config */ u32 curr_symbol_rate; /* pin-safe mode */ - bool pdr_safe_mode; /**< PDR safe mode activated */ + bool pdr_safe_mode; /*< PDR safe mode activated */ u16 pdr_safe_restore_val_gpio; u16 pdr_safe_restore_val_v_sync; u16 pdr_safe_restore_val_sma_rx; @@ -531,12 +531,12 @@ struct drxj_cfg_atv_output { enum drxj_cfg_oob_lo_power oob_lo_pow; struct drx_aud_data aud_data; - /**< audio storage */}; + /*< audio storage */}; /*------------------------------------------------------------------------- Access MACROS -------------------------------------------------------------------------*/ -/** +/* * \brief Compilable references to attributes * \param d pointer to demod instance * @@ -554,7 +554,7 @@ Access MACROS DEFINES -------------------------------------------------------------------------*/ -/** +/* * \def DRXJ_NTSC_CARRIER_FREQ_OFFSET * \brief Offset from picture carrier to centre frequency in kHz, in RF domain * @@ -569,7 +569,7 @@ DEFINES */ #define DRXJ_NTSC_CARRIER_FREQ_OFFSET ((s32)(1750)) -/** +/* * \def DRXJ_PAL_SECAM_BG_CARRIER_FREQ_OFFSET * \brief Offset from picture carrier to centre frequency in kHz, in RF domain * @@ -585,7 +585,7 @@ DEFINES */ #define DRXJ_PAL_SECAM_BG_CARRIER_FREQ_OFFSET ((s32)(2375)) -/** +/* * \def DRXJ_PAL_SECAM_DKIL_CARRIER_FREQ_OFFSET * \brief Offset from picture carrier to centre frequency in kHz, in RF domain * @@ -601,7 +601,7 @@ DEFINES */ #define DRXJ_PAL_SECAM_DKIL_CARRIER_FREQ_OFFSET ((s32)(2775)) -/** +/* * \def DRXJ_PAL_SECAM_LP_CARRIER_FREQ_OFFSET * \brief Offset from picture carrier to centre frequency in kHz, in RF domain * @@ -616,7 +616,7 @@ DEFINES */ #define DRXJ_PAL_SECAM_LP_CARRIER_FREQ_OFFSET ((s32)(-3255)) -/** +/* * \def DRXJ_FM_CARRIER_FREQ_OFFSET * \brief Offset from sound carrier to centre frequency in kHz, in RF domain * diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c index 7d04400b18dd..0696bc62dcc9 100644 --- a/drivers/media/dvb-frontends/drxd_hard.c +++ b/drivers/media/dvb-frontends/drxd_hard.c @@ -328,7 +328,7 @@ static int WriteTable(struct drxd_state *state, u8 * pTable) { int status = 0; - if (pTable == NULL) + if (!pTable) return 0; while (!status) { @@ -640,7 +640,7 @@ static int SetCfgIfAgc(struct drxd_state *state, struct SCfgAgc *cfg) const u16 maxRur = 8; static const u16 slowIncrDecLUT[] = { 3, 4, 4, 5, 6 }; - const u16 fastIncrDecLUT[] = { + static const u16 fastIncrDecLUT[] = { 14, 15, 15, 16, 17, 18, 18, 19, 20, 21, 22, 23, @@ -909,9 +909,8 @@ static int load_firmware(struct drxd_state *state, const char *fw_name) } state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL); - if (state->microcode == NULL) { + if (!state->microcode) { release_firmware(fw); - printk(KERN_ERR "drxd: firmware load failure: no memory\n"); return -ENOMEM; } @@ -2630,7 +2629,7 @@ static int DRXD_init(struct drxd_state *state, const u8 *fw, u32 fw_size) break; /* Apply I2c address patch to B1 */ - if (!state->type_A && state->m_HiI2cPatch != NULL) { + if (!state->type_A && state->m_HiI2cPatch) { status = WriteTable(state, state->m_HiI2cPatch); if (status < 0) break; diff --git a/drivers/media/dvb-frontends/drxk.h b/drivers/media/dvb-frontends/drxk.h index eb9bdc9f59c4..b16fedbb53a3 100644 --- a/drivers/media/dvb-frontends/drxk.h +++ b/drivers/media/dvb-frontends/drxk.h @@ -20,17 +20,18 @@ * @antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 * means that 1=DVBC, 0 = DVBT. Zero means the opposite. * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength. + * @chunk_size: maximum size for I2C messages * @microcode_name: Name of the firmware file with the microcode * @qam_demod_parameter_count: The number of parameters used for the command * to set the demodulator parameters. All * firmwares are using the 2-parameter commmand. - * An exception is the "drxk_a3.mc" firmware, + * An exception is the ``drxk_a3.mc`` firmware, * which uses the 4-parameter command. * A value of 0 (default) or lower indicates that * the correct number of parameters will be * automatically detected. * - * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is + * On the ``*_gpio`` vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is * UIO-3. */ struct drxk_config { @@ -52,6 +53,14 @@ struct drxk_config { }; #if IS_REACHABLE(CONFIG_DVB_DRXK) +/** + * Attach a drxk demod + * + * @config: pointer to &struct drxk_config with demod configuration. + * @i2c: i2c adapter to use. + * + * return: FE pointer on success, NULL on failure. + */ extern struct dvb_frontend *drxk_attach(const struct drxk_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index 48a8aad47a74..f59ac2e91c59 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -207,9 +207,9 @@ static inline u32 log10times100(u32 value) return (100L * intlog10(value)) >> 24; } -/****************************************************************************/ +/***************************************************************************/ /* I2C **********************************************************************/ -/****************************************************************************/ +/***************************************************************************/ static int drxk_i2c_lock(struct drxk_state *state) { @@ -3444,7 +3444,7 @@ error: /*============================================================================*/ -/** +/* * \brief Activate DVBT specific presets * \param demod instance of demodulator. * \return DRXStatus_t. @@ -3484,7 +3484,7 @@ error: /*============================================================================*/ -/** +/* * \brief Initialize channelswitch-independent settings for DVBT. * \param demod instance of demodulator. * \return DRXStatus_t. @@ -3696,7 +3696,7 @@ error: } /*============================================================================*/ -/** +/* * \brief start dvbt demodulating for channel. * \param demod instance of demodulator. * \return DRXStatus_t. @@ -3732,7 +3732,7 @@ error: /*============================================================================*/ -/** +/* * \brief Set up dvbt demodulator for channel. * \param demod instance of demodulator. * \return DRXStatus_t. @@ -4086,7 +4086,7 @@ error: /*============================================================================*/ -/** +/* * \brief Retrieve lock status . * \param demod Pointer to demodulator instance. * \param lockStat Pointer to lock status structure. @@ -4148,7 +4148,7 @@ static int power_up_qam(struct drxk_state *state) } -/** Power Down QAM */ +/* Power Down QAM */ static int power_down_qam(struct drxk_state *state) { u16 data = 0; @@ -4186,7 +4186,7 @@ error: /*============================================================================*/ -/** +/* * \brief Setup of the QAM Measurement intervals for signal quality * \param demod instance of demod. * \param modulation current modulation. @@ -4461,7 +4461,7 @@ error: /*============================================================================*/ -/** +/* * \brief QAM32 specific setup * \param demod instance of demod. * \return DRXStatus_t. @@ -4657,7 +4657,7 @@ error: /*============================================================================*/ -/** +/* * \brief QAM64 specific setup * \param demod instance of demod. * \return DRXStatus_t. @@ -4852,7 +4852,7 @@ error: /*============================================================================*/ -/** +/* * \brief QAM128 specific setup * \param demod: instance of demod. * \return DRXStatus_t. @@ -5049,7 +5049,7 @@ error: /*============================================================================*/ -/** +/* * \brief QAM256 specific setup * \param demod: instance of demod. * \return DRXStatus_t. @@ -5244,7 +5244,7 @@ error: /*============================================================================*/ -/** +/* * \brief Reset QAM block. * \param demod: instance of demod. * \param channel: pointer to channel data. @@ -5272,7 +5272,7 @@ error: /*============================================================================*/ -/** +/* * \brief Set QAM symbolrate. * \param demod: instance of demod. * \param channel: pointer to channel data. @@ -5341,7 +5341,7 @@ error: /*============================================================================*/ -/** +/* * \brief Get QAM lock status. * \param demod: instance of demod. * \param channel: pointer to channel data. diff --git a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c index 0b17a45c5640..bd4f8278c906 100644 --- a/drivers/media/dvb-frontends/ds3000.c +++ b/drivers/media/dvb-frontends/ds3000.c @@ -277,10 +277,8 @@ static int ds3000_writeFW(struct ds3000_state *state, int reg, u8 *buf; buf = kmalloc(33, GFP_KERNEL); - if (buf == NULL) { - printk(KERN_ERR "Unable to kmalloc\n"); + if (!buf) return -ENOMEM; - } *(buf) = reg; @@ -835,17 +833,15 @@ static const struct dvb_frontend_ops ds3000_ops; struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, struct i2c_adapter *i2c) { - struct ds3000_state *state = NULL; + struct ds3000_state *state; int ret; dprintk("%s\n", __func__); /* allocate memory for the internal state */ - state = kzalloc(sizeof(struct ds3000_state), GFP_KERNEL); - if (state == NULL) { - printk(KERN_ERR "Unable to kmalloc\n"); - goto error2; - } + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; state->config = config; state->i2c = i2c; @@ -854,8 +850,9 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, /* check if the demod is present */ ret = ds3000_readreg(state, 0x00) & 0xfe; if (ret != 0xe0) { + kfree(state); printk(KERN_ERR "Invalid probe, probably not a DS3000\n"); - goto error3; + return NULL; } printk(KERN_INFO "DS3000 chip version: %d.%d attached.\n", @@ -873,11 +870,6 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, */ ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF); return &state->frontend; - -error3: - kfree(state); -error2: - return NULL; } EXPORT_SYMBOL(ds3000_attach); diff --git a/drivers/media/dvb-frontends/dvb-pll.h b/drivers/media/dvb-frontends/dvb-pll.h index 6aaa9c6bff9c..212e0730f154 100644 --- a/drivers/media/dvb-frontends/dvb-pll.h +++ b/drivers/media/dvb-frontends/dvb-pll.h @@ -30,16 +30,17 @@ #define DVB_PLL_TDEE4 18 #define DVB_PLL_THOMSON_DTT7520X 19 +#if IS_REACHABLE(CONFIG_DVB_PLL) /** * Attach a dvb-pll to the supplied frontend structure. * - * @param fe Frontend to attach to. - * @param pll_addr i2c address of the PLL (if used). - * @param i2c i2c adapter to use (set to NULL if not used). - * @param pll_desc_id dvb_pll_desc to use. - * @return Frontend pointer on success, NULL on failure + * @fe: Frontend to attach to. + * @pll_addr: i2c address of the PLL (if used). + * @i2c: i2c adapter to use (set to NULL if not used). + * @pll_desc_id: dvb_pll_desc to use. + * + * return: Frontend pointer on success, NULL on failure */ -#if IS_REACHABLE(CONFIG_DVB_PLL) extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, diff --git a/drivers/media/dvb-frontends/helene.h b/drivers/media/dvb-frontends/helene.h index 333615491d9e..c9fc81c7e4e7 100644 --- a/drivers/media/dvb-frontends/helene.h +++ b/drivers/media/dvb-frontends/helene.h @@ -38,6 +38,7 @@ enum helene_xtal { * @set_tuner_priv: Callback function private context * @set_tuner_callback: Callback function that notifies the parent driver * which tuner is active now + * @xtal: Cristal frequency as described by &enum helene_xtal */ struct helene_config { u8 i2c_address; @@ -48,9 +49,31 @@ struct helene_config { }; #if IS_REACHABLE(CONFIG_DVB_HELENE) +/** + * Attach a helene tuner (terrestrial and cable standards) + * + * @fe: frontend to be attached + * @config: pointer to &struct helene_config with tuner configuration. + * @i2c: i2c adapter to use. + * + * return: FE pointer on success, NULL on failure. + */ extern struct dvb_frontend *helene_attach(struct dvb_frontend *fe, const struct helene_config *config, struct i2c_adapter *i2c); + +/** + * Attach a helene tuner (satellite standards) + * + * @fe: frontend to be attached + * @config: pointer to &struct helene_config with tuner configuration. + * @i2c: i2c adapter to use. + * + * return: FE pointer on success, NULL on failure. + */ +extern struct dvb_frontend *helene_attach_s(struct dvb_frontend *fe, + const struct helene_config *config, + struct i2c_adapter *i2c); #else static inline struct dvb_frontend *helene_attach(struct dvb_frontend *fe, const struct helene_config *config, @@ -59,13 +82,6 @@ static inline struct dvb_frontend *helene_attach(struct dvb_frontend *fe, pr_warn("%s: driver disabled by Kconfig\n", __func__); return NULL; } -#endif - -#if IS_REACHABLE(CONFIG_DVB_HELENE) -extern struct dvb_frontend *helene_attach_s(struct dvb_frontend *fe, - const struct helene_config *config, - struct i2c_adapter *i2c); -#else static inline struct dvb_frontend *helene_attach_s(struct dvb_frontend *fe, const struct helene_config *config, struct i2c_adapter *i2c) diff --git a/drivers/media/dvb-frontends/horus3a.h b/drivers/media/dvb-frontends/horus3a.h index 672a556df71a..9157fd037e2f 100644 --- a/drivers/media/dvb-frontends/horus3a.h +++ b/drivers/media/dvb-frontends/horus3a.h @@ -41,6 +41,15 @@ struct horus3a_config { }; #if IS_REACHABLE(CONFIG_DVB_HORUS3A) +/** + * Attach a horus3a tuner + * + * @fe: frontend to be attached + * @config: pointer to &struct helene_config with tuner configuration. + * @i2c: i2c adapter to use. + * + * return: FE pointer on success, NULL on failure. + */ extern struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe, const struct horus3a_config *config, struct i2c_adapter *i2c); diff --git a/drivers/media/dvb-frontends/ix2505v.c b/drivers/media/dvb-frontends/ix2505v.c index 534b24fa2b95..965012ad5c59 100644 --- a/drivers/media/dvb-frontends/ix2505v.c +++ b/drivers/media/dvb-frontends/ix2505v.c @@ -1,4 +1,4 @@ -/** +/* * Driver for Sharp IX2505V (marked B0017) DVB-S silicon tuner * * Copyright (C) 2010 Malcolm Priestley @@ -36,7 +36,7 @@ struct ix2505v_state { u32 frequency; }; -/** +/* * Data read format of the Sharp IX2505V B0017 * * byte1: 1 | 1 | 0 | 0 | 0 | MA1 | MA0 | 1 @@ -99,7 +99,7 @@ static void ix2505v_release(struct dvb_frontend *fe) } -/** +/* * Data write format of the Sharp IX2505V B0017 * * byte1: 1 | 1 | 0 | 0 | 0 | 0(MA1)| 0(MA0)| 0 diff --git a/drivers/media/dvb-frontends/ix2505v.h b/drivers/media/dvb-frontends/ix2505v.h index 0b0a431c74f6..49ed93e754ed 100644 --- a/drivers/media/dvb-frontends/ix2505v.h +++ b/drivers/media/dvb-frontends/ix2505v.h @@ -20,31 +20,33 @@ #include "dvb_frontend.h" /** - * Attach a ix2505v tuner to the supplied frontend structure. + * struct ix2505v_config - ix2505 attachment configuration * - * @param fe Frontend to attach to. - * @param config ix2505v_config structure - * @return FE pointer on success, NULL on failure. + * @tuner_address: tuner address + * @tuner_gain: Baseband AMP gain control 0/1=0dB(default) 2=-2bB 3=-4dB + * @tuner_chargepump: Charge pump output +/- 0=120 1=260 2=555 3=1200(default) + * @min_delay_ms: delay after tune + * @tuner_write_only: disables reads */ - struct ix2505v_config { u8 tuner_address; - - /*Baseband AMP gain control 0/1=0dB(default) 2=-2bB 3=-4dB */ u8 tuner_gain; - - /*Charge pump output +/- 0=120 1=260 2=555 3=1200(default) */ u8 tuner_chargepump; - - /* delay after tune */ int min_delay_ms; - - /* disables reads*/ u8 tuner_write_only; }; #if IS_REACHABLE(CONFIG_DVB_IX2505V) +/** + * Attach a ix2505v tuner to the supplied frontend structure. + * + * @fe: Frontend to attach to. + * @config: pointer to &struct ix2505v_config + * @i2c: pointer to &struct i2c_adapter. + * + * return: FE pointer on success, NULL on failure. + */ extern struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe, const struct ix2505v_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/l64781.c b/drivers/media/dvb-frontends/l64781.c index 68923c84679a..e5a6c1766664 100644 --- a/drivers/media/dvb-frontends/l64781.c +++ b/drivers/media/dvb-frontends/l64781.c @@ -517,7 +517,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config, state->i2c = i2c; state->first = 1; - /** + /* * the L64781 won't show up before we send the reset_and_configure() * broadcast. If nothing responds there is no L64781 on the bus... */ diff --git a/drivers/media/dvb-frontends/lg2160.c b/drivers/media/dvb-frontends/lg2160.c index 5798079add10..9854096839ae 100644 --- a/drivers/media/dvb-frontends/lg2160.c +++ b/drivers/media/dvb-frontends/lg2160.c @@ -1048,16 +1048,6 @@ fail: return ret; } -static int lg216x_get_property(struct dvb_frontend *fe, - struct dtv_property *tvp) -{ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - - return (DTV_ATSCMH_FIC_VER == tvp->cmd) ? - lg216x_get_frontend(fe, c) : 0; -} - - static int lg2160_set_frontend(struct dvb_frontend *fe) { struct lg216x_state *state = fe->demodulator_priv; @@ -1368,8 +1358,6 @@ static const struct dvb_frontend_ops lg2160_ops = { .init = lg216x_init, .sleep = lg216x_sleep, #endif - .get_property = lg216x_get_property, - .set_frontend = lg2160_set_frontend, .get_frontend = lg216x_get_frontend, .get_tune_settings = lg216x_get_tune_settings, @@ -1396,8 +1384,6 @@ static const struct dvb_frontend_ops lg2161_ops = { .init = lg216x_init, .sleep = lg216x_sleep, #endif - .get_property = lg216x_get_property, - .set_frontend = lg2160_set_frontend, .get_frontend = lg216x_get_frontend, .get_tune_settings = lg216x_get_tune_settings, diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c index c9b1eb38444e..724e9aac0f11 100644 --- a/drivers/media/dvb-frontends/lgdt3306a.c +++ b/drivers/media/dvb-frontends/lgdt3306a.c @@ -19,6 +19,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <asm/div64.h> +#include <linux/kernel.h> #include <linux/dvb/frontend.h> #include "dvb_math.h" #include "lgdt3306a.h" @@ -2072,7 +2073,7 @@ static const short regtab[] = { 0x30aa, /* MPEGLOCK */ }; -#define numDumpRegs (sizeof(regtab)/sizeof(regtab[0])) +#define numDumpRegs (ARRAY_SIZE(regtab)) static u8 regval1[numDumpRegs] = {0, }; static u8 regval2[numDumpRegs] = {0, }; diff --git a/drivers/media/dvb-frontends/m88ds3103.h b/drivers/media/dvb-frontends/m88ds3103.h index 04b355a005fb..1a8964a2265d 100644 --- a/drivers/media/dvb-frontends/m88ds3103.h +++ b/drivers/media/dvb-frontends/m88ds3103.h @@ -25,6 +25,34 @@ */ /** + * enum m88ds3103_ts_mode - TS connection mode + * @M88DS3103_TS_SERIAL: TS output pin D0, normal + * @M88DS3103_TS_SERIAL_D7: TS output pin D7 + * @M88DS3103_TS_PARALLEL: TS Parallel mode + * @M88DS3103_TS_CI: TS CI Mode + */ +enum m88ds3103_ts_mode { + M88DS3103_TS_SERIAL, + M88DS3103_TS_SERIAL_D7, + M88DS3103_TS_PARALLEL, + M88DS3103_TS_CI +}; + +/** + * enum m88ds3103_clock_out + * @M88DS3103_CLOCK_OUT_DISABLED: Clock output is disabled + * @M88DS3103_CLOCK_OUT_ENABLED: Clock output is enabled with crystal + * clock. + * @M88DS3103_CLOCK_OUT_ENABLED_DIV2: Clock output is enabled with half + * crystal clock. + */ +enum m88ds3103_clock_out { + M88DS3103_CLOCK_OUT_DISABLED, + M88DS3103_CLOCK_OUT_ENABLED, + M88DS3103_CLOCK_OUT_ENABLED_DIV2 +}; + +/** * struct m88ds3103_platform_data - Platform data for the m88ds3103 driver * @clk: Clock frequency. * @i2c_wr_max: Max bytes I2C adapter can write at once. @@ -44,24 +72,16 @@ * @get_dvb_frontend: Get DVB frontend. * @get_i2c_adapter: Get I2C adapter. */ - struct m88ds3103_platform_data { u32 clk; u16 i2c_wr_max; -#define M88DS3103_TS_SERIAL 0 /* TS output pin D0, normal */ -#define M88DS3103_TS_SERIAL_D7 1 /* TS output pin D7 */ -#define M88DS3103_TS_PARALLEL 2 /* TS Parallel mode */ -#define M88DS3103_TS_CI 3 /* TS CI Mode */ - u8 ts_mode:2; + enum m88ds3103_ts_mode ts_mode; u32 ts_clk; + enum m88ds3103_clock_out clk_out; u8 ts_clk_pol:1; u8 spec_inv:1; u8 agc; u8 agc_inv:1; -#define M88DS3103_CLOCK_OUT_DISABLED 0 -#define M88DS3103_CLOCK_OUT_ENABLED 1 -#define M88DS3103_CLOCK_OUT_ENABLED_DIV2 2 - u8 clk_out:2; u8 envelope_mode:1; u8 lnb_hv_pol:1; u8 lnb_en_pol:1; @@ -73,105 +93,60 @@ struct m88ds3103_platform_data { u8 attach_in_use:1; }; -/* - * Do not add new m88ds3103_attach() users! Use I2C bindings instead. +/** + * struct m88ds3103_config - m88ds3102 configuration + * + * @i2c_addr: I2C address. Default: none, must set. Example: 0x68, ... + * @clock: Device's clock. Default: none, must set. Example: 27000000 + * @i2c_wr_max: Max bytes I2C provider is asked to write at once. + * Default: none, must set. Example: 33, 65, ... + * @ts_mode: TS output mode, as defined by &enum m88ds3103_ts_mode. + * Default: M88DS3103_TS_SERIAL. + * @ts_clk: TS clk in KHz. Default: 0. + * @ts_clk_pol: TS clk polarity.Default: 0. + * 1-active at falling edge; 0-active at rising edge. + * @spec_inv: Spectrum inversion. Default: 0. + * @agc_inv: AGC polarity. Default: 0. + * @clock_out: Clock output, as defined by &enum m88ds3103_clock_out. + * Default: M88DS3103_CLOCK_OUT_DISABLED. + * @envelope_mode: DiSEqC envelope mode. Default: 0. + * @agc: AGC configuration. Default: none, must set. + * @lnb_hv_pol: LNB H/V pin polarity. Default: 0. Values: + * 1: pin high set to VOLTAGE_13, pin low to set VOLTAGE_18; + * 0: pin high set to VOLTAGE_18, pin low to set VOLTAGE_13. + * @lnb_en_pol: LNB enable pin polarity. Default: 0. Values: + * 1: pin high to enable, pin low to disable; + * 0: pin high to disable, pin low to enable. */ struct m88ds3103_config { - /* - * I2C address - * Default: none, must set - * 0x68, ... - */ u8 i2c_addr; - - /* - * clock - * Default: none, must set - * 27000000 - */ u32 clock; - - /* - * max bytes I2C provider is asked to write at once - * Default: none, must set - * 33, 65, ... - */ u16 i2c_wr_max; - - /* - * TS output mode - * Default: M88DS3103_TS_SERIAL - */ -#define M88DS3103_TS_SERIAL 0 /* TS output pin D0, normal */ -#define M88DS3103_TS_SERIAL_D7 1 /* TS output pin D7 */ -#define M88DS3103_TS_PARALLEL 2 /* TS Parallel mode */ -#define M88DS3103_TS_CI 3 /* TS CI Mode */ u8 ts_mode; - - /* - * TS clk in KHz - * Default: 0. - */ u32 ts_clk; - - /* - * TS clk polarity. - * Default: 0. 1-active at falling edge; 0-active at rising edge. - */ u8 ts_clk_pol:1; - - /* - * spectrum inversion - * Default: 0 - */ u8 spec_inv:1; - - /* - * AGC polarity - * Default: 0 - */ u8 agc_inv:1; - - /* - * clock output - * Default: M88DS3103_CLOCK_OUT_DISABLED - */ -#define M88DS3103_CLOCK_OUT_DISABLED 0 -#define M88DS3103_CLOCK_OUT_ENABLED 1 -#define M88DS3103_CLOCK_OUT_ENABLED_DIV2 2 u8 clock_out; - - /* - * DiSEqC envelope mode - * Default: 0 - */ u8 envelope_mode:1; - - /* - * AGC configuration - * Default: none, must set - */ u8 agc; - - /* - * LNB H/V pin polarity - * Default: 0. - * 1: pin high set to VOLTAGE_13, pin low to set VOLTAGE_18. - * 0: pin high set to VOLTAGE_18, pin low to set VOLTAGE_13. - */ u8 lnb_hv_pol:1; - - /* - * LNB enable pin polarity - * Default: 0. - * 1: pin high to enable, pin low to disable. - * 0: pin high to disable, pin low to enable. - */ u8 lnb_en_pol:1; }; #if defined(CONFIG_DVB_M88DS3103) || \ (defined(CONFIG_DVB_M88DS3103_MODULE) && defined(MODULE)) +/** + * Attach a m88ds3103 demod + * + * @config: pointer to &struct m88ds3103_config with demod configuration. + * @i2c: i2c adapter to use. + * @tuner_i2c: on success, returns the I2C adapter associated with + * m88ds3103 tuner. + * + * return: FE pointer on success, NULL on failure. + * Note: Do not add new m88ds3103_attach() users! Use I2C bindings instead. + */ extern struct dvb_frontend *m88ds3103_attach( const struct m88ds3103_config *config, struct i2c_adapter *i2c, diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index e8ac8c3e2ec0..bdaf9d235fed 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c @@ -2071,12 +2071,9 @@ struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, dev_dbg(&i2c->dev, "%s called.\n", __func__); /* allocate memory for the internal state */ - state = kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL); - if (state == NULL) { - dev_err(&i2c->dev, - "%s: unable to allocate memory for state\n", __func__); - goto error; - } + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; /* setup the state */ state->config = config; @@ -2089,22 +2086,16 @@ struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, /* Check if it is a mb86a20s frontend */ rev = mb86a20s_readreg(state, 0); - - if (rev == 0x13) { - dev_info(&i2c->dev, - "Detected a Fujitsu mb86a20s frontend\n"); - } else { + if (rev != 0x13) { + kfree(state); dev_dbg(&i2c->dev, "Frontend revision %d is unknown - aborting.\n", rev); - goto error; + return NULL; } + dev_info(&i2c->dev, "Detected a Fujitsu mb86a20s frontend\n"); return &state->frontend; - -error: - kfree(state); - return NULL; } EXPORT_SYMBOL(mb86a20s_attach); diff --git a/drivers/media/dvb-frontends/mb86a20s.h b/drivers/media/dvb-frontends/mb86a20s.h index dfb02db2126c..05c9725d1c5f 100644 --- a/drivers/media/dvb-frontends/mb86a20s.h +++ b/drivers/media/dvb-frontends/mb86a20s.h @@ -26,7 +26,6 @@ * @demod_address: the demodulator's i2c address * @is_serial: if true, TS is serial. Otherwise, TS is parallel */ - struct mb86a20s_config { u32 fclk; u8 demod_address; @@ -34,9 +33,17 @@ struct mb86a20s_config { }; #if IS_REACHABLE(CONFIG_DVB_MB86A20S) +/** + * Attach a mb86a20s demod + * + * @config: pointer to &struct mb86a20s_config with demod configuration. + * @i2c: i2c adapter to use. + * + * return: FE pointer on success, NULL on failure. + */ extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, struct i2c_adapter *i2c); -extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *); + #else static inline struct dvb_frontend *mb86a20s_attach( const struct mb86a20s_config *config, struct i2c_adapter *i2c) @@ -44,12 +51,6 @@ static inline struct dvb_frontend *mb86a20s_attach( printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } -static inline struct i2c_adapter * - mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *fe) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return NULL; -} #endif #endif /* MB86A20S */ diff --git a/drivers/media/dvb-frontends/mn88472.h b/drivers/media/dvb-frontends/mn88472.h index 323632523876..8cd5ef61903b 100644 --- a/drivers/media/dvb-frontends/mn88472.h +++ b/drivers/media/dvb-frontends/mn88472.h @@ -19,21 +19,21 @@ #include <linux/dvb/frontend.h> +/* Define old names for backward compatibility */ +#define VARIABLE_TS_CLOCK MN88472_TS_CLK_VARIABLE +#define FIXED_TS_CLOCK MN88472_TS_CLK_FIXED +#define SERIAL_TS_MODE MN88472_TS_MODE_SERIAL +#define PARALLEL_TS_MODE MN88472_TS_MODE_PARALLEL + /** * struct mn88472_config - Platform data for the mn88472 driver * @xtal: Clock frequency. * @ts_mode: TS mode. * @ts_clock: TS clock config. * @i2c_wr_max: Max number of bytes driver writes to I2C at once. - * @get_dvb_frontend: Get DVB frontend. + * @fe: pointer to a frontend pointer + * @get_dvb_frontend: Get DVB frontend callback. */ - -/* Define old names for backward compatibility */ -#define VARIABLE_TS_CLOCK MN88472_TS_CLK_VARIABLE -#define FIXED_TS_CLOCK MN88472_TS_CLK_FIXED -#define SERIAL_TS_MODE MN88472_TS_MODE_SERIAL -#define PARALLEL_TS_MODE MN88472_TS_MODE_PARALLEL - struct mn88472_config { unsigned int xtal; diff --git a/drivers/media/dvb-frontends/mxl5xx.c b/drivers/media/dvb-frontends/mxl5xx.c index 676c96c216c3..53064e11f5f1 100644 --- a/drivers/media/dvb-frontends/mxl5xx.c +++ b/drivers/media/dvb-frontends/mxl5xx.c @@ -43,7 +43,7 @@ #define BYTE2(v) ((v >> 16) & 0xff) #define BYTE3(v) ((v >> 24) & 0xff) -LIST_HEAD(mxllist); +static LIST_HEAD(mxllist); struct mxl_base { struct list_head mxllist; diff --git a/drivers/media/dvb-frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h index 0cde151e6608..458ac94e8a8b 100644 --- a/drivers/media/dvb-frontends/rtl2830.h +++ b/drivers/media/dvb-frontends/rtl2830.h @@ -32,7 +32,6 @@ * @pid_filter: Set PID to PID filter. * @pid_filter_ctrl: Control PID filter. */ - struct rtl2830_platform_data { u32 clk; bool spec_inv; diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index 03c0de039fa9..6a124ff71c2b 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -35,7 +35,6 @@ * @pid_filter: Set PID to PID filter. * @pid_filter_ctrl: Control PID filter. */ - struct rtl2832_platform_data { u32 clk; /* diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.h b/drivers/media/dvb-frontends/rtl2832_sdr.h index d8fc7e7212e3..8f88c2fb8627 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.h +++ b/drivers/media/dvb-frontends/rtl2832_sdr.h @@ -33,15 +33,11 @@ * struct rtl2832_sdr_platform_data - Platform data for the rtl2832_sdr driver * @clk: Clock frequency (4000000, 16000000, 25000000, 28800000). * @tuner: Used tuner model. - * @i2c_client: rtl2832 demod driver I2C client. - * @bulk_read: rtl2832 driver private I/O interface. - * @bulk_write: rtl2832 driver private I/O interface. - * @update_bits: rtl2832 driver private I/O interface. + * @regmap: pointer to &struct regmap. * @dvb_frontend: rtl2832 DVB frontend. * @v4l2_subdev: Tuner v4l2 controls. * @dvb_usb_device: DVB USB interface for USB streaming. */ - struct rtl2832_sdr_platform_data { u32 clk; /* diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 172fc367ccaa..41d9c513b7e8 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -696,7 +696,6 @@ static int si2168_probe(struct i2c_client *client, dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { ret = -ENOMEM; - dev_err(&client->dev, "kzalloc() failed\n"); goto err; } diff --git a/drivers/media/dvb-frontends/sp2.c b/drivers/media/dvb-frontends/sp2.c index 43d47dfcc7b8..53e66c232d3c 100644 --- a/drivers/media/dvb-frontends/sp2.c +++ b/drivers/media/dvb-frontends/sp2.c @@ -357,14 +357,14 @@ static int sp2_exit(struct i2c_client *client) dev_dbg(&client->dev, "\n"); - if (client == NULL) + if (!client) return 0; s = i2c_get_clientdata(client); - if (s == NULL) + if (!s) return 0; - if (s->ca.data == NULL) + if (!s->ca.data) return 0; dvb_ca_en50221_release(&s->ca); @@ -381,10 +381,9 @@ static int sp2_probe(struct i2c_client *client, dev_dbg(&client->dev, "\n"); - s = kzalloc(sizeof(struct sp2), GFP_KERNEL); + s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) { ret = -ENOMEM; - dev_err(&client->dev, "kzalloc() failed\n"); goto err; } diff --git a/drivers/media/dvb-frontends/sp887x.c b/drivers/media/dvb-frontends/sp887x.c index 7c511c3cd4ca..d2c402b52c6e 100644 --- a/drivers/media/dvb-frontends/sp887x.c +++ b/drivers/media/dvb-frontends/sp887x.c @@ -57,7 +57,7 @@ static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data) int ret; if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) { - /** + /* * in case of soft reset we ignore ACK errors... */ if (!(reg == 0xf1a && data == 0x000 && @@ -130,7 +130,7 @@ static void sp887x_setup_agc (struct sp887x_state* state) #define BLOCKSIZE 30 #define FW_SIZE 0x4000 -/** +/* * load firmware and setup MPEG interface... */ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware *fw) @@ -279,7 +279,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05) return 0; } -/** +/* * estimates division of two 24bit numbers, * derived from the ves1820/stv0299 driver code */ diff --git a/drivers/media/dvb-frontends/stb6000.h b/drivers/media/dvb-frontends/stb6000.h index 78e75dfc317f..e94a3d5facf6 100644 --- a/drivers/media/dvb-frontends/stb6000.h +++ b/drivers/media/dvb-frontends/stb6000.h @@ -26,15 +26,16 @@ #include <linux/i2c.h> #include "dvb_frontend.h" +#if IS_REACHABLE(CONFIG_DVB_STB6000) /** * Attach a stb6000 tuner to the supplied frontend structure. * - * @param fe Frontend to attach to. - * @param addr i2c address of the tuner. - * @param i2c i2c adapter to use. - * @return FE pointer on success, NULL on failure. + * @fe: Frontend to attach to. + * @addr: i2c address of the tuner. + * @i2c: i2c adapter to use. + * + * return: FE pointer on success, NULL on failure. */ -#if IS_REACHABLE(CONFIG_DVB_STB6000) extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/stv0288.c b/drivers/media/dvb-frontends/stv0288.c index 45cbc898ad25..67f91814b9f7 100644 --- a/drivers/media/dvb-frontends/stv0288.c +++ b/drivers/media/dvb-frontends/stv0288.c @@ -447,12 +447,6 @@ static int stv0288_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p) -{ - dprintk("%s(..)\n", __func__); - return 0; -} - static int stv0288_set_frontend(struct dvb_frontend *fe) { struct stv0288_state *state = fe->demodulator_priv; @@ -567,7 +561,6 @@ static const struct dvb_frontend_ops stv0288_ops = { .set_tone = stv0288_set_tone, .set_voltage = stv0288_set_voltage, - .set_property = stv0288_set_property, .set_frontend = stv0288_set_frontend, }; diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c index b36b21a13201..b1f3d675d316 100644 --- a/drivers/media/dvb-frontends/stv0299.c +++ b/drivers/media/dvb-frontends/stv0299.c @@ -368,7 +368,7 @@ static int stv0299_set_voltage(struct dvb_frontend *fe, reg0x08 = stv0299_readreg (state, 0x08); reg0x0c = stv0299_readreg (state, 0x0c); - /** + /* * H/V switching over OP0, OP1 and OP2 are LNB power enable bits */ reg0x0c &= 0x0f; diff --git a/drivers/media/dvb-frontends/stv6110.c b/drivers/media/dvb-frontends/stv6110.c index e4fd9c1b0560..6aad0efa3174 100644 --- a/drivers/media/dvb-frontends/stv6110.c +++ b/drivers/media/dvb-frontends/stv6110.c @@ -258,11 +258,9 @@ static int stv6110_get_frequency(struct dvb_frontend *fe, u32 *frequency) static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency) { struct stv6110_priv *priv = fe->tuner_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; u8 ret = 0x04; u32 divider, ref, p, presc, i, result_freq, vco_freq; s32 p_calc, p_calc_opt = 1000, r_div, r_div_opt = 0, p_val; - s32 srate; dprintk("%s, freq=%d kHz, mclk=%d Hz\n", __func__, frequency, priv->mclk); @@ -273,13 +271,6 @@ static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency) ((((priv->mclk / 1000000) - 16) & 0x1f) << 3); /* BB_GAIN = db/2 */ - if (fe->ops.set_property && fe->ops.get_property) { - srate = c->symbol_rate; - dprintk("%s: Get Frontend parameters: srate=%d\n", - __func__, srate); - } else - srate = 15000000; - priv->regs[RSTV6110_CTRL2] &= ~0x0f; priv->regs[RSTV6110_CTRL2] |= (priv->gain & 0x0f); diff --git a/drivers/media/dvb-frontends/tda10071.h b/drivers/media/dvb-frontends/tda10071.h index 8f184026ee11..da1a87bc1603 100644 --- a/drivers/media/dvb-frontends/tda10071.h +++ b/drivers/media/dvb-frontends/tda10071.h @@ -38,7 +38,6 @@ * @tuner_i2c_addr: CX24118A tuner I2C address (0x14, 0x54, ...). * @get_dvb_frontend: Get DVB frontend. */ - struct tda10071_platform_data { u32 clk; u16 i2c_wr_max; diff --git a/drivers/media/dvb-frontends/tda826x.h b/drivers/media/dvb-frontends/tda826x.h index 81abe1aebe9f..6a7bed12e741 100644 --- a/drivers/media/dvb-frontends/tda826x.h +++ b/drivers/media/dvb-frontends/tda826x.h @@ -29,11 +29,12 @@ /** * Attach a tda826x tuner to the supplied frontend structure. * - * @param fe Frontend to attach to. - * @param addr i2c address of the tuner. - * @param i2c i2c adapter to use. - * @param has_loopthrough Set to 1 if the card has a loopthrough RF connector. - * @return FE pointer on success, NULL on failure. + * @fe: Frontend to attach to. + * @addr: i2c address of the tuner. + * @i2c: i2c adapter to use. + * @has_loopthrough: Set to 1 if the card has a loopthrough RF connector. + * + * return: FE pointer on success, NULL on failure. */ #if IS_REACHABLE(CONFIG_DVB_TDA826X) extern struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe, int addr, diff --git a/drivers/media/dvb-frontends/tua6100.c b/drivers/media/dvb-frontends/tua6100.c index 18e6d4c5be21..1d41abd47f04 100644 --- a/drivers/media/dvb-frontends/tua6100.c +++ b/drivers/media/dvb-frontends/tua6100.c @@ -1,4 +1,4 @@ -/** +/* * Driver for Infineon tua6100 pll. * * (c) 2006 Andrew de Quincey diff --git a/drivers/media/dvb-frontends/tua6100.h b/drivers/media/dvb-frontends/tua6100.h index 9f15cbdfdeca..6c098a894ea6 100644 --- a/drivers/media/dvb-frontends/tua6100.h +++ b/drivers/media/dvb-frontends/tua6100.h @@ -1,4 +1,4 @@ -/** +/* * Driver for Infineon tua6100 PLL. * * (c) 2006 Andrew de Quincey diff --git a/drivers/media/dvb-frontends/zd1301_demod.h b/drivers/media/dvb-frontends/zd1301_demod.h index ceb2e05e873c..6cd8f6f9c415 100644 --- a/drivers/media/dvb-frontends/zd1301_demod.h +++ b/drivers/media/dvb-frontends/zd1301_demod.h @@ -27,7 +27,6 @@ * @reg_read: Register read callback. * @reg_write: Register write callback. */ - struct zd1301_demod_platform_data { void *reg_priv; int (*reg_read)(void *, u16, u8 *); @@ -41,8 +40,7 @@ struct zd1301_demod_platform_data { * * Return: Pointer to DVB frontend which given platform device owns. */ - -struct dvb_frontend *zd1301_demod_get_dvb_frontend(struct platform_device *); +struct dvb_frontend *zd1301_demod_get_dvb_frontend(struct platform_device *pdev); /** * zd1301_demod_get_i2c_adapter() - Get pointer to I2C adapter @@ -50,11 +48,16 @@ struct dvb_frontend *zd1301_demod_get_dvb_frontend(struct platform_device *); * * Return: Pointer to I2C adapter which given platform device owns. */ - -struct i2c_adapter *zd1301_demod_get_i2c_adapter(struct platform_device *); +struct i2c_adapter *zd1301_demod_get_i2c_adapter(struct platform_device *pdev); #else +/** + * zd1301_demod_get_dvb_frontend() - Attach a zd1301 frontend + * @dev: Pointer to platform device + * + * Return: Pointer to %struct dvb_frontend or NULL if attach fails. + */ static inline struct dvb_frontend *zd1301_demod_get_dvb_frontend(struct platform_device *dev) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); diff --git a/drivers/media/dvb-frontends/zl10036.c b/drivers/media/dvb-frontends/zl10036.c index 062282739ce5..89dd65ae88ad 100644 --- a/drivers/media/dvb-frontends/zl10036.c +++ b/drivers/media/dvb-frontends/zl10036.c @@ -1,4 +1,4 @@ -/** +/* * Driver for Zarlink zl10036 DVB-S silicon tuner * * Copyright (C) 2006 Tino Reichardt @@ -157,7 +157,7 @@ static int zl10036_sleep(struct dvb_frontend *fe) return ret; } -/** +/* * register map of the ZL10036/ZL10038 * * reg[default] content @@ -219,7 +219,7 @@ static int zl10036_set_bandwidth(struct zl10036_state *state, u32 fbw) if (fbw <= 28820) { br = _BR_MAXIMUM; } else { - /** + /* * f(bw)=34,6MHz f(xtal)=10.111MHz * br = (10111/34600) * 63 * 1/K = 14; */ @@ -315,7 +315,7 @@ static int zl10036_set_params(struct dvb_frontend *fe) || (frequency > fe->ops.info.frequency_max)) return -EINVAL; - /** + /* * alpha = 1.35 for dvb-s * fBW = (alpha*symbolrate)/(2*0.8) * 1.35 / (2*0.8) = 27 / 32 diff --git a/drivers/media/dvb-frontends/zl10036.h b/drivers/media/dvb-frontends/zl10036.h index 88751adfecf7..ec90ca927739 100644 --- a/drivers/media/dvb-frontends/zl10036.h +++ b/drivers/media/dvb-frontends/zl10036.h @@ -20,20 +20,20 @@ #include <linux/i2c.h> #include "dvb_frontend.h" -/** - * Attach a zl10036 tuner to the supplied frontend structure. - * - * @param fe Frontend to attach to. - * @param config zl10036_config structure - * @return FE pointer on success, NULL on failure. - */ - struct zl10036_config { u8 tuner_address; int rf_loop_enable; }; #if IS_REACHABLE(CONFIG_DVB_ZL10036) +/** + * Attach a zl10036 tuner to the supplied frontend structure. + * + * @fe: Frontend to attach to. + * @config: zl10036_config structure. + * @i2c: pointer to struct i2c_adapter. + * return: FE pointer on success, NULL on failure. + */ extern struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe, const struct zl10036_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 94153895fcd4..cb5d7ff82915 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -354,6 +354,14 @@ config VIDEO_TC358743 To compile this driver as a module, choose M here: the module will be called tc358743. +config VIDEO_TC358743_CEC + bool "Enable Toshiba TC358743 CEC support" + depends on VIDEO_TC358743 + select CEC_CORE + ---help--- + When selected the tc358743 will support the optional + HDMI CEC feature. + config VIDEO_TVP514X tristate "Texas Instruments TVP514x video decoder" depends on VIDEO_V4L2 && I2C @@ -547,6 +555,14 @@ config VIDEO_APTINA_PLL config VIDEO_SMIAPP_PLL tristate +config VIDEO_IMX274 + tristate "Sony IMX274 sensor support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a V4L2 sensor-level driver for the Sony IMX274 + CMOS image sensor. + config VIDEO_OV2640 tristate "OmniVision OV2640 sensor support" depends on VIDEO_V4L2 && I2C @@ -660,6 +676,7 @@ config VIDEO_OV13858 tristate "OmniVision OV13858 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT + select V4L2_FWNODE ---help--- This is a Video4Linux2 sensor-level driver for the OmniVision OV13858 camera. diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index f104650d6000..548a9efce966 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -93,5 +93,6 @@ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o obj-$(CONFIG_VIDEO_OV2659) += ov2659.o obj-$(CONFIG_VIDEO_TC358743) += tc358743.o +obj-$(CONFIG_VIDEO_IMX274) += imx274.o obj-$(CONFIG_SDR_MAX2175) += max2175.o diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 3df28f2f9b38..6fb818a775db 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -1328,7 +1328,7 @@ static int adv7180_probe(struct i2c_client *client, state->input = 0; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &adv7180_ops); - sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; ret = adv7180_init_controls(state); if (ret) diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c b/drivers/media/i2c/adv748x/adv748x-afe.c index b33ccfc08708..4aa8e45b5cd3 100644 --- a/drivers/media/i2c/adv748x/adv748x-afe.c +++ b/drivers/media/i2c/adv748x/adv748x-afe.c @@ -217,6 +217,7 @@ static int adv748x_afe_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { struct adv748x_afe *afe = adv748x_sd_to_afe(sd); struct adv748x_state *state = adv748x_afe_to_state(afe); + int afe_std; int ret; mutex_lock(&state->mutex); @@ -235,8 +236,12 @@ static int adv748x_afe_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) /* Read detected standard */ ret = adv748x_afe_status(afe, NULL, std); + afe_std = adv748x_afe_std(afe->curr_norm); + if (afe_std < 0) + goto unlock; + /* Restore original state */ - adv748x_afe_set_video_standard(state, afe->curr_norm); + adv748x_afe_set_video_standard(state, afe_std); unlock: mutex_unlock(&state->mutex); diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index f289b8aca1da..c786cd125417 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -1948,7 +1948,7 @@ static int adv76xx_set_format(struct v4l2_subdev *sd, return -EINVAL; info = adv76xx_format_info(state, format->format.code); - if (info == NULL) + if (!info) info = adv76xx_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8); adv76xx_fill_format(state, &format->format); @@ -2256,7 +2256,7 @@ static int adv76xx_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) return 0; } - if (data == NULL) + if (!data) return -ENODATA; if (edid->start_block >= state->edid.blocks) @@ -3316,10 +3316,8 @@ static int adv76xx_probe(struct i2c_client *client, client->addr << 1); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); - if (!state) { - v4l_err(client, "Could not allocate adv76xx_state memory!\n"); + if (!state) return -ENOMEM; - } state->i2c_clients[ADV76XX_PAGE_IO] = client; @@ -3482,7 +3480,7 @@ static int adv76xx_probe(struct i2c_client *client, state->i2c_clients[i] = adv76xx_dummy_client(sd, state->pdata.i2c_addresses[i], 0xf2 + i); - if (state->i2c_clients[i] == NULL) { + if (!state->i2c_clients[i]) { err = -ENOMEM; v4l2_err(sd, "failed to create i2c client %u\n", i); goto err_i2c; diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 65f34e7e146f..136aa80a834b 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -3467,11 +3467,9 @@ static int adv7842_probe(struct i2c_client *client, return -ENODEV; } - state = devm_kzalloc(&client->dev, sizeof(struct adv7842_state), GFP_KERNEL); - if (!state) { - v4l_err(client, "Could not allocate adv7842_state memory!\n"); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); + if (!state) return -ENOMEM; - } /* platform data */ state->pdata = *pdata; diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index 39f51daa7558..f38bf819d805 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -1745,7 +1745,7 @@ static int cx25840_g_std(struct v4l2_subdev *sd, v4l2_std_id *std) { struct i2c_client *client = v4l2_get_subdevdata(sd); - v4l2_std_id stds[] = { + static const v4l2_std_id stds[] = { /* 0000 */ V4L2_STD_UNKNOWN, /* 0001 */ V4L2_STD_NTSC_M, diff --git a/drivers/media/i2c/dw9714.c b/drivers/media/i2c/dw9714.c index 95af4fc99cd0..ed01e8bd4331 100644 --- a/drivers/media/i2c/dw9714.c +++ b/drivers/media/i2c/dw9714.c @@ -21,6 +21,11 @@ #define DW9714_NAME "dw9714" #define DW9714_MAX_FOCUS_POS 1023 /* + * This sets the minimum granularity for the focus positions. + * A value of 1 gives maximum accuracy for a desired focus position + */ +#define DW9714_FOCUS_STEPS 1 +/* * This acts as the minimum granularity of lens movement. * Keep this value power of 2, so the control steps can be * uniformly adjusted for gradual lens movement, with desired @@ -137,7 +142,7 @@ static int dw9714_init_controls(struct dw9714_device *dev_vcm) v4l2_ctrl_handler_init(hdl, 1); v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, - 0, DW9714_MAX_FOCUS_POS, DW9714_CTRL_STEPS, 0); + 0, DW9714_MAX_FOCUS_POS, DW9714_FOCUS_STEPS, 0); if (hdl->error) dev_err(&client->dev, "%s fail error: 0x%x\n", diff --git a/drivers/media/i2c/et8ek8/Kconfig b/drivers/media/i2c/et8ek8/Kconfig index 14399365ad7f..9fe409e95666 100644 --- a/drivers/media/i2c/et8ek8/Kconfig +++ b/drivers/media/i2c/et8ek8/Kconfig @@ -1,6 +1,7 @@ config VIDEO_ET8EK8 tristate "ET8EK8 camera sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE ---help--- This is a driver for the Toshiba ET8EK8 5 MP camera sensor. It is used for example in Nokia N900 (RX-51). diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c index c14f0fd6ded3..e9eff9039ef5 100644 --- a/drivers/media/i2c/et8ek8/et8ek8_driver.c +++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c @@ -1453,7 +1453,7 @@ static int et8ek8_probe(struct i2c_client *client, goto err_mutex; } - ret = v4l2_async_register_subdev(&sensor->subdev); + ret = v4l2_async_register_subdev_sensor_common(&sensor->subdev); if (ret < 0) goto err_entity; diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c new file mode 100644 index 000000000000..2f71af2f90bf --- /dev/null +++ b/drivers/media/i2c/imx274.c @@ -0,0 +1,1810 @@ +/* + * imx274.c - IMX274 CMOS Image Sensor driver + * + * Copyright (C) 2017, Leopard Imaging, Inc. + * + * Leon Luo <leonl@leopardimaging.com> + * Edwin Zou <edwinz@leopardimaging.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/of_gpio.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/v4l2-mediabus.h> +#include <linux/videodev2.h> + +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-subdev.h> + +/* + * See "SHR, SVR Setting" in datasheet + */ +#define IMX274_DEFAULT_FRAME_LENGTH (4550) +#define IMX274_MAX_FRAME_LENGTH (0x000fffff) + +/* + * See "Frame Rate Adjustment" in datasheet + */ +#define IMX274_PIXCLK_CONST1 (72000000) +#define IMX274_PIXCLK_CONST2 (1000000) + +/* + * The input gain is shifted by IMX274_GAIN_SHIFT to get + * decimal number. The real gain is + * (float)input_gain_value / (1 << IMX274_GAIN_SHIFT) + */ +#define IMX274_GAIN_SHIFT (8) +#define IMX274_GAIN_SHIFT_MASK ((1 << IMX274_GAIN_SHIFT) - 1) + +/* + * See "Analog Gain" and "Digital Gain" in datasheet + * min gain is 1X + * max gain is calculated based on IMX274_GAIN_REG_MAX + */ +#define IMX274_GAIN_REG_MAX (1957) +#define IMX274_MIN_GAIN (0x01 << IMX274_GAIN_SHIFT) +#define IMX274_MAX_ANALOG_GAIN ((2048 << IMX274_GAIN_SHIFT)\ + / (2048 - IMX274_GAIN_REG_MAX)) +#define IMX274_MAX_DIGITAL_GAIN (8) +#define IMX274_DEF_GAIN (20 << IMX274_GAIN_SHIFT) +#define IMX274_GAIN_CONST (2048) /* for gain formula */ + +/* + * 1 line time in us = (HMAX / 72), minimal is 4 lines + */ +#define IMX274_MIN_EXPOSURE_TIME (4 * 260 / 72) + +#define IMX274_DEFAULT_MODE IMX274_MODE_3840X2160 +#define IMX274_MAX_WIDTH (3840) +#define IMX274_MAX_HEIGHT (2160) +#define IMX274_MAX_FRAME_RATE (120) +#define IMX274_MIN_FRAME_RATE (5) +#define IMX274_DEF_FRAME_RATE (60) + +/* + * register SHR is limited to (SVR value + 1) x VMAX value - 4 + */ +#define IMX274_SHR_LIMIT_CONST (4) + +/* + * Constants for sensor reset delay + */ +#define IMX274_RESET_DELAY1 (2000) +#define IMX274_RESET_DELAY2 (2200) + +/* + * shift and mask constants + */ +#define IMX274_SHIFT_8_BITS (8) +#define IMX274_SHIFT_16_BITS (16) +#define IMX274_MASK_LSB_2_BITS (0x03) +#define IMX274_MASK_LSB_3_BITS (0x07) +#define IMX274_MASK_LSB_4_BITS (0x0f) +#define IMX274_MASK_LSB_8_BITS (0x00ff) + +#define DRIVER_NAME "IMX274" + +/* + * IMX274 register definitions + */ +#define IMX274_FRAME_LENGTH_ADDR_1 0x30FA /* VMAX, MSB */ +#define IMX274_FRAME_LENGTH_ADDR_2 0x30F9 /* VMAX */ +#define IMX274_FRAME_LENGTH_ADDR_3 0x30F8 /* VMAX, LSB */ +#define IMX274_SVR_REG_MSB 0x300F /* SVR */ +#define IMX274_SVR_REG_LSB 0x300E /* SVR */ +#define IMX274_HMAX_REG_MSB 0x30F7 /* HMAX */ +#define IMX274_HMAX_REG_LSB 0x30F6 /* HMAX */ +#define IMX274_COARSE_TIME_ADDR_MSB 0x300D /* SHR */ +#define IMX274_COARSE_TIME_ADDR_LSB 0x300C /* SHR */ +#define IMX274_ANALOG_GAIN_ADDR_LSB 0x300A /* ANALOG GAIN LSB */ +#define IMX274_ANALOG_GAIN_ADDR_MSB 0x300B /* ANALOG GAIN MSB */ +#define IMX274_DIGITAL_GAIN_REG 0x3012 /* Digital Gain */ +#define IMX274_VFLIP_REG 0x301A /* VERTICAL FLIP */ +#define IMX274_TEST_PATTERN_REG 0x303D /* TEST PATTERN */ +#define IMX274_STANDBY_REG 0x3000 /* STANDBY */ + +#define IMX274_TABLE_WAIT_MS 0 +#define IMX274_TABLE_END 1 + +/* + * imx274 I2C operation related structure + */ +struct reg_8 { + u16 addr; + u8 val; +}; + +static const struct regmap_config imx274_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, +}; + +enum imx274_mode { + IMX274_MODE_3840X2160, + IMX274_MODE_1920X1080, + IMX274_MODE_1280X720, + + IMX274_MODE_START_STREAM_1, + IMX274_MODE_START_STREAM_2, + IMX274_MODE_START_STREAM_3, + IMX274_MODE_START_STREAM_4, + IMX274_MODE_STOP_STREAM +}; + +/* + * imx274 format related structure + */ +struct imx274_frmfmt { + u32 mbus_code; + enum v4l2_colorspace colorspace; + struct v4l2_frmsize_discrete size; + enum imx274_mode mode; +}; + +/* + * imx274 test pattern related structure + */ +enum { + TEST_PATTERN_DISABLED = 0, + TEST_PATTERN_ALL_000H, + TEST_PATTERN_ALL_FFFH, + TEST_PATTERN_ALL_555H, + TEST_PATTERN_ALL_AAAH, + TEST_PATTERN_VSP_5AH, /* VERTICAL STRIPE PATTERN 555H/AAAH */ + TEST_PATTERN_VSP_A5H, /* VERTICAL STRIPE PATTERN AAAH/555H */ + TEST_PATTERN_VSP_05H, /* VERTICAL STRIPE PATTERN 000H/555H */ + TEST_PATTERN_VSP_50H, /* VERTICAL STRIPE PATTERN 555H/000H */ + TEST_PATTERN_VSP_0FH, /* VERTICAL STRIPE PATTERN 000H/FFFH */ + TEST_PATTERN_VSP_F0H, /* VERTICAL STRIPE PATTERN FFFH/000H */ + TEST_PATTERN_H_COLOR_BARS, + TEST_PATTERN_V_COLOR_BARS, +}; + +static const char * const tp_qmenu[] = { + "Disabled", + "All 000h Pattern", + "All FFFh Pattern", + "All 555h Pattern", + "All AAAh Pattern", + "Vertical Stripe (555h / AAAh)", + "Vertical Stripe (AAAh / 555h)", + "Vertical Stripe (000h / 555h)", + "Vertical Stripe (555h / 000h)", + "Vertical Stripe (000h / FFFh)", + "Vertical Stripe (FFFh / 000h)", + "Horizontal Color Bars", + "Vertical Color Bars", +}; + +/* + * All-pixel scan mode (10-bit) + * imx274 mode1(refer to datasheet) register configuration with + * 3840x2160 resolution, raw10 data and mipi four lane output + */ +static const struct reg_8 imx274_mode1_3840x2160_raw10[] = { + {0x3004, 0x01}, + {0x3005, 0x01}, + {0x3006, 0x00}, + {0x3007, 0x02}, + + {0x3018, 0xA2}, /* output XVS, HVS */ + + {0x306B, 0x05}, + {0x30E2, 0x01}, + {0x30F6, 0x07}, /* HMAX, 263 */ + {0x30F7, 0x01}, /* HMAX */ + + {0x30dd, 0x01}, /* crop to 2160 */ + {0x30de, 0x06}, + {0x30df, 0x00}, + {0x30e0, 0x12}, + {0x30e1, 0x00}, + {0x3037, 0x01}, /* to crop to 3840 */ + {0x3038, 0x0c}, + {0x3039, 0x00}, + {0x303a, 0x0c}, + {0x303b, 0x0f}, + + {0x30EE, 0x01}, + {0x3130, 0x86}, + {0x3131, 0x08}, + {0x3132, 0x7E}, + {0x3133, 0x08}, + {0x3342, 0x0A}, + {0x3343, 0x00}, + {0x3344, 0x16}, + {0x3345, 0x00}, + {0x33A6, 0x01}, + {0x3528, 0x0E}, + {0x3554, 0x1F}, + {0x3555, 0x01}, + {0x3556, 0x01}, + {0x3557, 0x01}, + {0x3558, 0x01}, + {0x3559, 0x00}, + {0x355A, 0x00}, + {0x35BA, 0x0E}, + {0x366A, 0x1B}, + {0x366B, 0x1A}, + {0x366C, 0x19}, + {0x366D, 0x17}, + {0x3A41, 0x08}, + + {IMX274_TABLE_END, 0x00} +}; + +/* + * Horizontal/vertical 2/2-line binning + * (Horizontal and vertical weightedbinning, 10-bit) + * imx274 mode3(refer to datasheet) register configuration with + * 1920x1080 resolution, raw10 data and mipi four lane output + */ +static const struct reg_8 imx274_mode3_1920x1080_raw10[] = { + {0x3004, 0x02}, + {0x3005, 0x21}, + {0x3006, 0x00}, + {0x3007, 0x11}, + + {0x3018, 0xA2}, /* output XVS, HVS */ + + {0x306B, 0x05}, + {0x30E2, 0x02}, + + {0x30F6, 0x04}, /* HMAX, 260 */ + {0x30F7, 0x01}, /* HMAX */ + + {0x30dd, 0x01}, /* to crop to 1920x1080 */ + {0x30de, 0x05}, + {0x30df, 0x00}, + {0x30e0, 0x04}, + {0x30e1, 0x00}, + {0x3037, 0x01}, + {0x3038, 0x0c}, + {0x3039, 0x00}, + {0x303a, 0x0c}, + {0x303b, 0x0f}, + + {0x30EE, 0x01}, + {0x3130, 0x4E}, + {0x3131, 0x04}, + {0x3132, 0x46}, + {0x3133, 0x04}, + {0x3342, 0x0A}, + {0x3343, 0x00}, + {0x3344, 0x1A}, + {0x3345, 0x00}, + {0x33A6, 0x01}, + {0x3528, 0x0E}, + {0x3554, 0x00}, + {0x3555, 0x01}, + {0x3556, 0x01}, + {0x3557, 0x01}, + {0x3558, 0x01}, + {0x3559, 0x00}, + {0x355A, 0x00}, + {0x35BA, 0x0E}, + {0x366A, 0x1B}, + {0x366B, 0x1A}, + {0x366C, 0x19}, + {0x366D, 0x17}, + {0x3A41, 0x08}, + + {IMX274_TABLE_END, 0x00} +}; + +/* + * Vertical 2/3 subsampling binning horizontal 3 binning + * imx274 mode5(refer to datasheet) register configuration with + * 1280x720 resolution, raw10 data and mipi four lane output + */ +static const struct reg_8 imx274_mode5_1280x720_raw10[] = { + {0x3004, 0x03}, + {0x3005, 0x31}, + {0x3006, 0x00}, + {0x3007, 0x09}, + + {0x3018, 0xA2}, /* output XVS, HVS */ + + {0x306B, 0x05}, + {0x30E2, 0x03}, + + {0x30F6, 0x04}, /* HMAX, 260 */ + {0x30F7, 0x01}, /* HMAX */ + + {0x30DD, 0x01}, + {0x30DE, 0x07}, + {0x30DF, 0x00}, + {0x40E0, 0x04}, + {0x30E1, 0x00}, + {0x3030, 0xD4}, + {0x3031, 0x02}, + {0x3032, 0xD0}, + {0x3033, 0x02}, + + {0x30EE, 0x01}, + {0x3130, 0xE2}, + {0x3131, 0x02}, + {0x3132, 0xDE}, + {0x3133, 0x02}, + {0x3342, 0x0A}, + {0x3343, 0x00}, + {0x3344, 0x1B}, + {0x3345, 0x00}, + {0x33A6, 0x01}, + {0x3528, 0x0E}, + {0x3554, 0x00}, + {0x3555, 0x01}, + {0x3556, 0x01}, + {0x3557, 0x01}, + {0x3558, 0x01}, + {0x3559, 0x00}, + {0x355A, 0x00}, + {0x35BA, 0x0E}, + {0x366A, 0x1B}, + {0x366B, 0x19}, + {0x366C, 0x17}, + {0x366D, 0x17}, + {0x3A41, 0x04}, + + {IMX274_TABLE_END, 0x00} +}; + +/* + * imx274 first step register configuration for + * starting stream + */ +static const struct reg_8 imx274_start_1[] = { + {IMX274_STANDBY_REG, 0x12}, + {IMX274_TABLE_END, 0x00} +}; + +/* + * imx274 second step register configuration for + * starting stream + */ +static const struct reg_8 imx274_start_2[] = { + {0x3120, 0xF0}, /* clock settings */ + {0x3121, 0x00}, /* clock settings */ + {0x3122, 0x02}, /* clock settings */ + {0x3129, 0x9C}, /* clock settings */ + {0x312A, 0x02}, /* clock settings */ + {0x312D, 0x02}, /* clock settings */ + + {0x310B, 0x00}, + + /* PLSTMG */ + {0x304C, 0x00}, /* PLSTMG01 */ + {0x304D, 0x03}, + {0x331C, 0x1A}, + {0x331D, 0x00}, + {0x3502, 0x02}, + {0x3529, 0x0E}, + {0x352A, 0x0E}, + {0x352B, 0x0E}, + {0x3538, 0x0E}, + {0x3539, 0x0E}, + {0x3553, 0x00}, + {0x357D, 0x05}, + {0x357F, 0x05}, + {0x3581, 0x04}, + {0x3583, 0x76}, + {0x3587, 0x01}, + {0x35BB, 0x0E}, + {0x35BC, 0x0E}, + {0x35BD, 0x0E}, + {0x35BE, 0x0E}, + {0x35BF, 0x0E}, + {0x366E, 0x00}, + {0x366F, 0x00}, + {0x3670, 0x00}, + {0x3671, 0x00}, + + /* PSMIPI */ + {0x3304, 0x32}, /* PSMIPI1 */ + {0x3305, 0x00}, + {0x3306, 0x32}, + {0x3307, 0x00}, + {0x3590, 0x32}, + {0x3591, 0x00}, + {0x3686, 0x32}, + {0x3687, 0x00}, + + {IMX274_TABLE_END, 0x00} +}; + +/* + * imx274 third step register configuration for + * starting stream + */ +static const struct reg_8 imx274_start_3[] = { + {IMX274_STANDBY_REG, 0x00}, + {0x303E, 0x02}, /* SYS_MODE = 2 */ + {IMX274_TABLE_END, 0x00} +}; + +/* + * imx274 forth step register configuration for + * starting stream + */ +static const struct reg_8 imx274_start_4[] = { + {0x30F4, 0x00}, + {0x3018, 0xA2}, /* XHS VHS OUTUPT */ + {IMX274_TABLE_END, 0x00} +}; + +/* + * imx274 register configuration for stoping stream + */ +static const struct reg_8 imx274_stop[] = { + {IMX274_STANDBY_REG, 0x01}, + {IMX274_TABLE_END, 0x00} +}; + +/* + * imx274 disable test pattern register configuration + */ +static const struct reg_8 imx274_tp_disabled[] = { + {0x303C, 0x00}, + {0x377F, 0x00}, + {0x3781, 0x00}, + {0x370B, 0x00}, + {IMX274_TABLE_END, 0x00} +}; + +/* + * imx274 test pattern register configuration + * reg 0x303D defines the test pattern modes + */ +static const struct reg_8 imx274_tp_regs[] = { + {0x303C, 0x11}, + {0x370E, 0x01}, + {0x377F, 0x01}, + {0x3781, 0x01}, + {0x370B, 0x11}, + {IMX274_TABLE_END, 0x00} +}; + +static const struct reg_8 *mode_table[] = { + [IMX274_MODE_3840X2160] = imx274_mode1_3840x2160_raw10, + [IMX274_MODE_1920X1080] = imx274_mode3_1920x1080_raw10, + [IMX274_MODE_1280X720] = imx274_mode5_1280x720_raw10, + + [IMX274_MODE_START_STREAM_1] = imx274_start_1, + [IMX274_MODE_START_STREAM_2] = imx274_start_2, + [IMX274_MODE_START_STREAM_3] = imx274_start_3, + [IMX274_MODE_START_STREAM_4] = imx274_start_4, + [IMX274_MODE_STOP_STREAM] = imx274_stop, +}; + +/* + * imx274 format related structure + */ +static const struct imx274_frmfmt imx274_formats[] = { + {MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {3840, 2160}, + IMX274_MODE_3840X2160}, + {MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {1920, 1080}, + IMX274_MODE_1920X1080}, + {MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {1280, 720}, + IMX274_MODE_1280X720}, +}; + +/* + * minimal frame length for each mode + * refer to datasheet section "Frame Rate Adjustment (CSI-2)" + */ +static const int min_frame_len[] = { + 4550, /* mode 1, 4K */ + 2310, /* mode 3, 1080p */ + 2310 /* mode 5, 720p */ +}; + +/* + * minimal numbers of SHR register + * refer to datasheet table "Shutter Setting (CSI-2)" + */ +static const int min_SHR[] = { + 12, /* mode 1, 4K */ + 8, /* mode 3, 1080p */ + 8 /* mode 5, 720p */ +}; + +static const int max_frame_rate[] = { + 60, /* mode 1 , 4K */ + 120, /* mode 3, 1080p */ + 120 /* mode 5, 720p */ +}; + +/* + * Number of clocks per internal offset period + * a constant based on mode + * refer to section "Integration Time in Each Readout Drive Mode (CSI-2)" + * in the datasheet + * for the implemented 3 modes, it happens to be the same number + */ +static const int nocpiop[] = { + 112, /* mode 1 , 4K */ + 112, /* mode 3, 1080p */ + 112 /* mode 5, 720p */ +}; + +/* + * struct imx274_ctrls - imx274 ctrl structure + * @handler: V4L2 ctrl handler structure + * @exposure: Pointer to expsure ctrl structure + * @gain: Pointer to gain ctrl structure + * @vflip: Pointer to vflip ctrl structure + * @test_pattern: Pointer to test pattern ctrl structure + */ +struct imx274_ctrls { + struct v4l2_ctrl_handler handler; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *gain; + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *test_pattern; +}; + +/* + * struct stim274 - imx274 device structure + * @sd: V4L2 subdevice structure + * @pd: Media pad structure + * @client: Pointer to I2C client + * @ctrls: imx274 control structure + * @format: V4L2 media bus frame format structure + * @frame_rate: V4L2 frame rate structure + * @regmap: Pointer to regmap structure + * @reset_gpio: Pointer to reset gpio + * @lock: Mutex structure + * @mode_index: Resolution mode index + */ +struct stimx274 { + struct v4l2_subdev sd; + struct media_pad pad; + struct i2c_client *client; + struct imx274_ctrls ctrls; + struct v4l2_mbus_framefmt format; + struct v4l2_fract frame_interval; + struct regmap *regmap; + struct gpio_desc *reset_gpio; + struct mutex lock; /* mutex lock for operations */ + u32 mode_index; +}; + +/* + * Function declaration + */ +static int imx274_set_gain(struct stimx274 *priv, struct v4l2_ctrl *ctrl); +static int imx274_set_exposure(struct stimx274 *priv, int val); +static int imx274_set_vflip(struct stimx274 *priv, int val); +static int imx274_set_test_pattern(struct stimx274 *priv, int val); +static int imx274_set_frame_interval(struct stimx274 *priv, + struct v4l2_fract frame_interval); + +static inline void msleep_range(unsigned int delay_base) +{ + usleep_range(delay_base * 1000, delay_base * 1000 + 500); +} + +/* + * v4l2_ctrl and v4l2_subdev related operations + */ +static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) +{ + return &container_of(ctrl->handler, + struct stimx274, ctrls.handler)->sd; +} + +static inline struct stimx274 *to_imx274(struct v4l2_subdev *sd) +{ + return container_of(sd, struct stimx274, sd); +} + +/* + * imx274_regmap_util_write_table_8 - Function for writing register table + * @regmap: Pointer to device reg map structure + * @table: Table containing register values + * @wait_ms_addr: Flag for performing delay + * @end_addr: Flag for incating end of table + * + * This is used to write register table into sensor's reg map. + * + * Return: 0 on success, errors otherwise + */ +static int imx274_regmap_util_write_table_8(struct regmap *regmap, + const struct reg_8 table[], + u16 wait_ms_addr, u16 end_addr) +{ + int err; + const struct reg_8 *next; + u8 val; + + int range_start = -1; + int range_count = 0; + u8 range_vals[16]; + int max_range_vals = ARRAY_SIZE(range_vals); + + for (next = table;; next++) { + if ((next->addr != range_start + range_count) || + (next->addr == end_addr) || + (next->addr == wait_ms_addr) || + (range_count == max_range_vals)) { + if (range_count == 1) + err = regmap_write(regmap, + range_start, range_vals[0]); + else if (range_count > 1) + err = regmap_bulk_write(regmap, range_start, + &range_vals[0], + range_count); + + if (err) + return err; + + range_start = -1; + range_count = 0; + + /* Handle special address values */ + if (next->addr == end_addr) + break; + + if (next->addr == wait_ms_addr) { + msleep_range(next->val); + continue; + } + } + + val = next->val; + + if (range_start == -1) + range_start = next->addr; + + range_vals[range_count++] = val; + } + return 0; +} + +static inline int imx274_read_reg(struct stimx274 *priv, u16 addr, u8 *val) +{ + int err; + + err = regmap_read(priv->regmap, addr, (unsigned int *)val); + if (err) + dev_err(&priv->client->dev, + "%s : i2c read failed, addr = %x\n", __func__, addr); + else + dev_dbg(&priv->client->dev, + "%s : addr 0x%x, val=0x%x\n", __func__, + addr, *val); + return err; +} + +static inline int imx274_write_reg(struct stimx274 *priv, u16 addr, u8 val) +{ + int err; + + err = regmap_write(priv->regmap, addr, val); + if (err) + dev_err(&priv->client->dev, + "%s : i2c write failed, %x = %x\n", __func__, + addr, val); + else + dev_dbg(&priv->client->dev, + "%s : addr 0x%x, val=0x%x\n", __func__, + addr, val); + return err; +} + +static int imx274_write_table(struct stimx274 *priv, const struct reg_8 table[]) +{ + return imx274_regmap_util_write_table_8(priv->regmap, + table, IMX274_TABLE_WAIT_MS, IMX274_TABLE_END); +} + +/* + * imx274_mode_regs - Function for set mode registers per mode index + * @priv: Pointer to device structure + * @mode: Mode index value + * + * This is used to start steam per mode index. + * mode = 0, start stream for sensor Mode 1: 4K/raw10 + * mode = 1, start stream for sensor Mode 3: 1080p/raw10 + * mode = 2, start stream for sensor Mode 5: 720p/raw10 + * + * Return: 0 on success, errors otherwise + */ +static int imx274_mode_regs(struct stimx274 *priv, int mode) +{ + int err = 0; + + err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_1]); + if (err) + return err; + + err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_2]); + if (err) + return err; + + err = imx274_write_table(priv, mode_table[mode]); + + return err; +} + +/* + * imx274_start_stream - Function for starting stream per mode index + * @priv: Pointer to device structure + * + * Return: 0 on success, errors otherwise + */ +static int imx274_start_stream(struct stimx274 *priv) +{ + int err = 0; + + /* + * Refer to "Standby Cancel Sequence when using CSI-2" in + * imx274 datasheet, it should wait 10ms or more here. + * give it 1 extra ms for margin + */ + msleep_range(11); + err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_3]); + if (err) + return err; + + /* + * Refer to "Standby Cancel Sequence when using CSI-2" in + * imx274 datasheet, it should wait 7ms or more here. + * give it 1 extra ms for margin + */ + msleep_range(8); + err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_4]); + if (err) + return err; + + return 0; +} + +/* + * imx274_reset - Function called to reset the sensor + * @priv: Pointer to device structure + * @rst: Input value for determining the sensor's end state after reset + * + * Set the senor in reset and then + * if rst = 0, keep it in reset; + * if rst = 1, bring it out of reset. + * + */ +static void imx274_reset(struct stimx274 *priv, int rst) +{ + gpiod_set_value_cansleep(priv->reset_gpio, 0); + usleep_range(IMX274_RESET_DELAY1, IMX274_RESET_DELAY2); + gpiod_set_value_cansleep(priv->reset_gpio, !!rst); + usleep_range(IMX274_RESET_DELAY1, IMX274_RESET_DELAY2); +} + +/** + * imx274_s_ctrl - This is used to set the imx274 V4L2 controls + * @ctrl: V4L2 control to be set + * + * This function is used to set the V4L2 controls for the imx274 sensor. + * + * Return: 0 on success, errors otherwise + */ +static int imx274_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = ctrl_to_sd(ctrl); + struct stimx274 *imx274 = to_imx274(sd); + int ret = -EINVAL; + + dev_dbg(&imx274->client->dev, + "%s : s_ctrl: %s, value: %d\n", __func__, + ctrl->name, ctrl->val); + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + dev_dbg(&imx274->client->dev, + "%s : set V4L2_CID_EXPOSURE\n", __func__); + ret = imx274_set_exposure(imx274, ctrl->val); + break; + + case V4L2_CID_GAIN: + dev_dbg(&imx274->client->dev, + "%s : set V4L2_CID_GAIN\n", __func__); + ret = imx274_set_gain(imx274, ctrl); + break; + + case V4L2_CID_VFLIP: + dev_dbg(&imx274->client->dev, + "%s : set V4L2_CID_VFLIP\n", __func__); + ret = imx274_set_vflip(imx274, ctrl->val); + break; + + case V4L2_CID_TEST_PATTERN: + dev_dbg(&imx274->client->dev, + "%s : set V4L2_CID_TEST_PATTERN\n", __func__); + ret = imx274_set_test_pattern(imx274, ctrl->val); + break; + } + + return ret; +} + +/** + * imx274_get_fmt - Get the pad format + * @sd: Pointer to V4L2 Sub device structure + * @cfg: Pointer to sub device pad information structure + * @fmt: Pointer to pad level media bus format + * + * This function is used to get the pad format information. + * + * Return: 0 on success + */ +static int imx274_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct stimx274 *imx274 = to_imx274(sd); + + mutex_lock(&imx274->lock); + fmt->format = imx274->format; + mutex_unlock(&imx274->lock); + return 0; +} + +/** + * imx274_set_fmt - This is used to set the pad format + * @sd: Pointer to V4L2 Sub device structure + * @cfg: Pointer to sub device pad information structure + * @format: Pointer to pad level media bus format + * + * This function is used to set the pad format. + * + * Return: 0 on success + */ +static int imx274_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct v4l2_mbus_framefmt *fmt = &format->format; + struct stimx274 *imx274 = to_imx274(sd); + struct i2c_client *client = imx274->client; + int index; + + dev_dbg(&client->dev, + "%s: width = %d height = %d code = %d mbus_code = %d\n", + __func__, fmt->width, fmt->height, fmt->code, + imx274_formats[imx274->mode_index].mbus_code); + + mutex_lock(&imx274->lock); + + for (index = 0; index < ARRAY_SIZE(imx274_formats); index++) { + if (imx274_formats[index].size.width == fmt->width && + imx274_formats[index].size.height == fmt->height) + break; + } + + if (index >= ARRAY_SIZE(imx274_formats)) { + /* default to first format */ + index = 0; + } + + imx274->mode_index = index; + + if (fmt->width > IMX274_MAX_WIDTH) + fmt->width = IMX274_MAX_WIDTH; + if (fmt->height > IMX274_MAX_HEIGHT) + fmt->height = IMX274_MAX_HEIGHT; + fmt->width = fmt->width & (~IMX274_MASK_LSB_2_BITS); + fmt->height = fmt->height & (~IMX274_MASK_LSB_2_BITS); + fmt->field = V4L2_FIELD_NONE; + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) + cfg->try_fmt = *fmt; + else + imx274->format = *fmt; + + mutex_unlock(&imx274->lock); + return 0; +} + +/** + * imx274_g_frame_interval - Get the frame interval + * @sd: Pointer to V4L2 Sub device structure + * @fi: Pointer to V4l2 Sub device frame interval structure + * + * This function is used to get the frame interval. + * + * Return: 0 on success + */ +static int imx274_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct stimx274 *imx274 = to_imx274(sd); + + fi->interval = imx274->frame_interval; + dev_dbg(&imx274->client->dev, "%s frame rate = %d / %d\n", + __func__, imx274->frame_interval.numerator, + imx274->frame_interval.denominator); + + return 0; +} + +/** + * imx274_s_frame_interval - Set the frame interval + * @sd: Pointer to V4L2 Sub device structure + * @fi: Pointer to V4l2 Sub device frame interval structure + * + * This function is used to set the frame intervavl. + * + * Return: 0 on success + */ +static int imx274_s_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct stimx274 *imx274 = to_imx274(sd); + struct v4l2_ctrl *ctrl = imx274->ctrls.exposure; + int min, max, def; + int ret; + + mutex_lock(&imx274->lock); + ret = imx274_set_frame_interval(imx274, fi->interval); + + if (!ret) { + /* + * exposure time range is decided by frame interval + * need to update it after frame interal changes + */ + min = IMX274_MIN_EXPOSURE_TIME; + max = fi->interval.numerator * 1000000 + / fi->interval.denominator; + def = max; + if (__v4l2_ctrl_modify_range(ctrl, min, max, 1, def)) { + dev_err(&imx274->client->dev, + "Exposure ctrl range update failed\n"); + goto unlock; + } + + /* update exposure time accordingly */ + imx274_set_exposure(imx274, imx274->ctrls.exposure->val); + + dev_dbg(&imx274->client->dev, "set frame interval to %uus\n", + fi->interval.numerator * 1000000 + / fi->interval.denominator); + } + +unlock: + mutex_unlock(&imx274->lock); + + return ret; +} + +/** + * imx274_load_default - load default control values + * @priv: Pointer to device structure + * + * Return: 0 on success, errors otherwise + */ +static int imx274_load_default(struct stimx274 *priv) +{ + int ret; + + /* load default control values */ + priv->frame_interval.numerator = 1; + priv->frame_interval.denominator = IMX274_DEF_FRAME_RATE; + priv->ctrls.exposure->val = 1000000 / IMX274_DEF_FRAME_RATE; + priv->ctrls.gain->val = IMX274_DEF_GAIN; + priv->ctrls.vflip->val = 0; + priv->ctrls.test_pattern->val = TEST_PATTERN_DISABLED; + + /* update frame rate */ + ret = imx274_set_frame_interval(priv, + priv->frame_interval); + if (ret) + return ret; + + /* update exposure time */ + ret = v4l2_ctrl_s_ctrl(priv->ctrls.exposure, priv->ctrls.exposure->val); + if (ret) + return ret; + + /* update gain */ + ret = v4l2_ctrl_s_ctrl(priv->ctrls.gain, priv->ctrls.gain->val); + if (ret) + return ret; + + /* update vflip */ + ret = v4l2_ctrl_s_ctrl(priv->ctrls.vflip, priv->ctrls.vflip->val); + if (ret) + return ret; + + return 0; +} + +/** + * imx274_s_stream - It is used to start/stop the streaming. + * @sd: V4L2 Sub device + * @on: Flag (True / False) + * + * This function controls the start or stop of streaming for the + * imx274 sensor. + * + * Return: 0 on success, errors otherwise + */ +static int imx274_s_stream(struct v4l2_subdev *sd, int on) +{ + struct stimx274 *imx274 = to_imx274(sd); + int ret = 0; + + dev_dbg(&imx274->client->dev, "%s : %s, mode index = %d\n", __func__, + on ? "Stream Start" : "Stream Stop", imx274->mode_index); + + mutex_lock(&imx274->lock); + + if (on) { + /* load mode registers */ + ret = imx274_mode_regs(imx274, imx274->mode_index); + if (ret) + goto fail; + + /* + * update frame rate & expsoure. if the last mode is different, + * HMAX could be changed. As the result, frame rate & exposure + * are changed. + * gain is not affected. + */ + ret = imx274_set_frame_interval(imx274, + imx274->frame_interval); + if (ret) + goto fail; + + /* update exposure time */ + ret = __v4l2_ctrl_s_ctrl(imx274->ctrls.exposure, + imx274->ctrls.exposure->val); + if (ret) + goto fail; + + /* start stream */ + ret = imx274_start_stream(imx274); + if (ret) + goto fail; + } else { + /* stop stream */ + ret = imx274_write_table(imx274, + mode_table[IMX274_MODE_STOP_STREAM]); + if (ret) + goto fail; + } + + mutex_unlock(&imx274->lock); + dev_dbg(&imx274->client->dev, + "%s : Done: mode = %d\n", __func__, imx274->mode_index); + return 0; + +fail: + mutex_unlock(&imx274->lock); + dev_err(&imx274->client->dev, "s_stream failed\n"); + return ret; +} + +/* + * imx274_get_frame_length - Function for obtaining current frame length + * @priv: Pointer to device structure + * @val: Pointer to obainted value + * + * frame_length = vmax x (svr + 1), in unit of hmax. + * + * Return: 0 on success + */ +static int imx274_get_frame_length(struct stimx274 *priv, u32 *val) +{ + int err; + u16 svr; + u32 vmax; + u8 reg_val[3]; + + /* svr */ + err = imx274_read_reg(priv, IMX274_SVR_REG_LSB, ®_val[0]); + if (err) + goto fail; + + err = imx274_read_reg(priv, IMX274_SVR_REG_MSB, ®_val[1]); + if (err) + goto fail; + + svr = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0]; + + /* vmax */ + err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_3, ®_val[0]); + if (err) + goto fail; + + err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_2, ®_val[1]); + if (err) + goto fail; + + err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_1, ®_val[2]); + if (err) + goto fail; + + vmax = ((reg_val[2] & IMX274_MASK_LSB_3_BITS) << IMX274_SHIFT_16_BITS) + + (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0]; + + *val = vmax * (svr + 1); + + return 0; + +fail: + dev_err(&priv->client->dev, "%s error = %d\n", __func__, err); + return err; +} + +static int imx274_clamp_coarse_time(struct stimx274 *priv, u32 *val, + u32 *frame_length) +{ + int err; + + err = imx274_get_frame_length(priv, frame_length); + if (err) + return err; + + if (*frame_length < min_frame_len[priv->mode_index]) + *frame_length = min_frame_len[priv->mode_index]; + + *val = *frame_length - *val; /* convert to raw shr */ + if (*val > *frame_length - IMX274_SHR_LIMIT_CONST) + *val = *frame_length - IMX274_SHR_LIMIT_CONST; + else if (*val < min_SHR[priv->mode_index]) + *val = min_SHR[priv->mode_index]; + + return 0; +} + +/* + * imx274_set_digital gain - Function called when setting digital gain + * @priv: Pointer to device structure + * @dgain: Value of digital gain. + * + * Digital gain has only 4 steps: 1x, 2x, 4x, and 8x + * + * Return: 0 on success + */ +static int imx274_set_digital_gain(struct stimx274 *priv, u32 dgain) +{ + u8 reg_val; + + reg_val = ffs(dgain); + + if (reg_val) + reg_val--; + + reg_val = clamp(reg_val, (u8)0, (u8)3); + + return imx274_write_reg(priv, IMX274_DIGITAL_GAIN_REG, + reg_val & IMX274_MASK_LSB_4_BITS); +} + +static inline void imx274_calculate_gain_regs(struct reg_8 regs[2], u16 gain) +{ + regs->addr = IMX274_ANALOG_GAIN_ADDR_MSB; + regs->val = (gain >> IMX274_SHIFT_8_BITS) & IMX274_MASK_LSB_3_BITS; + + (regs + 1)->addr = IMX274_ANALOG_GAIN_ADDR_LSB; + (regs + 1)->val = (gain) & IMX274_MASK_LSB_8_BITS; +} + +/* + * imx274_set_gain - Function called when setting gain + * @priv: Pointer to device structure + * @val: Value of gain. the real value = val << IMX274_GAIN_SHIFT; + * @ctrl: v4l2 control pointer + * + * Set the gain based on input value. + * The caller should hold the mutex lock imx274->lock if necessary + * + * Return: 0 on success + */ +static int imx274_set_gain(struct stimx274 *priv, struct v4l2_ctrl *ctrl) +{ + struct reg_8 reg_list[2]; + int err; + u32 gain, analog_gain, digital_gain, gain_reg; + int i; + + gain = (u32)(ctrl->val); + + dev_dbg(&priv->client->dev, + "%s : input gain = %d.%d\n", __func__, + gain >> IMX274_GAIN_SHIFT, + ((gain & IMX274_GAIN_SHIFT_MASK) * 100) >> IMX274_GAIN_SHIFT); + + if (gain > IMX274_MAX_DIGITAL_GAIN * IMX274_MAX_ANALOG_GAIN) + gain = IMX274_MAX_DIGITAL_GAIN * IMX274_MAX_ANALOG_GAIN; + else if (gain < IMX274_MIN_GAIN) + gain = IMX274_MIN_GAIN; + + if (gain <= IMX274_MAX_ANALOG_GAIN) + digital_gain = 1; + else if (gain <= IMX274_MAX_ANALOG_GAIN * 2) + digital_gain = 2; + else if (gain <= IMX274_MAX_ANALOG_GAIN * 4) + digital_gain = 4; + else + digital_gain = IMX274_MAX_DIGITAL_GAIN; + + analog_gain = gain / digital_gain; + + dev_dbg(&priv->client->dev, + "%s : digital gain = %d, analog gain = %d.%d\n", + __func__, digital_gain, analog_gain >> IMX274_GAIN_SHIFT, + ((analog_gain & IMX274_GAIN_SHIFT_MASK) * 100) + >> IMX274_GAIN_SHIFT); + + err = imx274_set_digital_gain(priv, digital_gain); + if (err) + goto fail; + + /* convert to register value, refer to imx274 datasheet */ + gain_reg = (u32)IMX274_GAIN_CONST - + (IMX274_GAIN_CONST << IMX274_GAIN_SHIFT) / analog_gain; + if (gain_reg > IMX274_GAIN_REG_MAX) + gain_reg = IMX274_GAIN_REG_MAX; + + imx274_calculate_gain_regs(reg_list, (u16)gain_reg); + + for (i = 0; i < ARRAY_SIZE(reg_list); i++) { + err = imx274_write_reg(priv, reg_list[i].addr, + reg_list[i].val); + if (err) + goto fail; + } + + if (IMX274_GAIN_CONST - gain_reg == 0) { + err = -EINVAL; + goto fail; + } + + /* convert register value back to gain value */ + ctrl->val = (IMX274_GAIN_CONST << IMX274_GAIN_SHIFT) + / (IMX274_GAIN_CONST - gain_reg) * digital_gain; + + dev_dbg(&priv->client->dev, + "%s : GAIN control success, gain_reg = %d, new gain = %d\n", + __func__, gain_reg, ctrl->val); + + return 0; + +fail: + dev_err(&priv->client->dev, "%s error = %d\n", __func__, err); + return err; +} + +static inline void imx274_calculate_coarse_time_regs(struct reg_8 regs[2], + u32 coarse_time) +{ + regs->addr = IMX274_COARSE_TIME_ADDR_MSB; + regs->val = (coarse_time >> IMX274_SHIFT_8_BITS) + & IMX274_MASK_LSB_8_BITS; + (regs + 1)->addr = IMX274_COARSE_TIME_ADDR_LSB; + (regs + 1)->val = (coarse_time) & IMX274_MASK_LSB_8_BITS; +} + +/* + * imx274_set_coarse_time - Function called when setting SHR value + * @priv: Pointer to device structure + * @val: Value for exposure time in number of line_length, or [HMAX] + * + * Set SHR value based on input value. + * + * Return: 0 on success + */ +static int imx274_set_coarse_time(struct stimx274 *priv, u32 *val) +{ + struct reg_8 reg_list[2]; + int err; + u32 coarse_time, frame_length; + int i; + + coarse_time = *val; + + /* convert exposure_time to appropriate SHR value */ + err = imx274_clamp_coarse_time(priv, &coarse_time, &frame_length); + if (err) + goto fail; + + /* prepare SHR registers */ + imx274_calculate_coarse_time_regs(reg_list, coarse_time); + + /* write to SHR registers */ + for (i = 0; i < ARRAY_SIZE(reg_list); i++) { + err = imx274_write_reg(priv, reg_list[i].addr, + reg_list[i].val); + if (err) + goto fail; + } + + *val = frame_length - coarse_time; + return 0; + +fail: + dev_err(&priv->client->dev, "%s error = %d\n", __func__, err); + return err; +} + +/* + * imx274_set_exposure - Function called when setting exposure time + * @priv: Pointer to device structure + * @val: Variable for exposure time, in the unit of micro-second + * + * Set exposure time based on input value. + * The caller should hold the mutex lock imx274->lock if necessary + * + * Return: 0 on success + */ +static int imx274_set_exposure(struct stimx274 *priv, int val) +{ + int err; + u16 hmax; + u8 reg_val[2]; + u32 coarse_time; /* exposure time in unit of line (HMAX)*/ + + dev_dbg(&priv->client->dev, + "%s : EXPOSURE control input = %d\n", __func__, val); + + /* step 1: convert input exposure_time (val) into number of 1[HMAX] */ + + /* obtain HMAX value */ + err = imx274_read_reg(priv, IMX274_HMAX_REG_LSB, ®_val[0]); + if (err) + goto fail; + err = imx274_read_reg(priv, IMX274_HMAX_REG_MSB, ®_val[1]); + if (err) + goto fail; + hmax = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0]; + if (hmax == 0) { + err = -EINVAL; + goto fail; + } + + coarse_time = (IMX274_PIXCLK_CONST1 / IMX274_PIXCLK_CONST2 * val + - nocpiop[priv->mode_index]) / hmax; + + /* step 2: convert exposure_time into SHR value */ + + /* set SHR */ + err = imx274_set_coarse_time(priv, &coarse_time); + if (err) + goto fail; + + priv->ctrls.exposure->val = + (coarse_time * hmax + nocpiop[priv->mode_index]) + / (IMX274_PIXCLK_CONST1 / IMX274_PIXCLK_CONST2); + + dev_dbg(&priv->client->dev, + "%s : EXPOSURE control success\n", __func__); + return 0; + +fail: + dev_err(&priv->client->dev, "%s error = %d\n", __func__, err); + + return err; +} + +/* + * imx274_set_vflip - Function called when setting vertical flip + * @priv: Pointer to device structure + * @val: Value for vflip setting + * + * Set vertical flip based on input value. + * val = 0: normal, no vertical flip + * val = 1: vertical flip enabled + * The caller should hold the mutex lock imx274->lock if necessary + * + * Return: 0 on success + */ +static int imx274_set_vflip(struct stimx274 *priv, int val) +{ + int err; + + err = imx274_write_reg(priv, IMX274_VFLIP_REG, val); + if (err) { + dev_err(&priv->client->dev, "VFILP control error\n"); + return err; + } + + dev_dbg(&priv->client->dev, + "%s : VFLIP control success\n", __func__); + + return 0; +} + +/* + * imx274_set_test_pattern - Function called when setting test pattern + * @priv: Pointer to device structure + * @val: Variable for test pattern + * + * Set to different test patterns based on input value. + * + * Return: 0 on success + */ +static int imx274_set_test_pattern(struct stimx274 *priv, int val) +{ + int err = 0; + + if (val == TEST_PATTERN_DISABLED) { + err = imx274_write_table(priv, imx274_tp_disabled); + } else if (val <= TEST_PATTERN_V_COLOR_BARS) { + err = imx274_write_reg(priv, IMX274_TEST_PATTERN_REG, val - 1); + if (!err) + err = imx274_write_table(priv, imx274_tp_regs); + } else { + err = -EINVAL; + } + + if (!err) + dev_dbg(&priv->client->dev, + "%s : TEST PATTERN control success\n", __func__); + else + dev_err(&priv->client->dev, "%s error = %d\n", __func__, err); + + return err; +} + +static inline void imx274_calculate_frame_length_regs(struct reg_8 regs[3], + u32 frame_length) +{ + regs->addr = IMX274_FRAME_LENGTH_ADDR_1; + regs->val = (frame_length >> IMX274_SHIFT_16_BITS) + & IMX274_MASK_LSB_4_BITS; + (regs + 1)->addr = IMX274_FRAME_LENGTH_ADDR_2; + (regs + 1)->val = (frame_length >> IMX274_SHIFT_8_BITS) + & IMX274_MASK_LSB_8_BITS; + (regs + 2)->addr = IMX274_FRAME_LENGTH_ADDR_3; + (regs + 2)->val = (frame_length) & IMX274_MASK_LSB_8_BITS; +} + +/* + * imx274_set_frame_length - Function called when setting frame length + * @priv: Pointer to device structure + * @val: Variable for frame length (= VMAX, i.e. vertical drive period length) + * + * Set frame length based on input value. + * + * Return: 0 on success + */ +static int imx274_set_frame_length(struct stimx274 *priv, u32 val) +{ + struct reg_8 reg_list[3]; + int err; + u32 frame_length; + int i; + + dev_dbg(&priv->client->dev, "%s : input length = %d\n", + __func__, val); + + frame_length = (u32)val; + + imx274_calculate_frame_length_regs(reg_list, frame_length); + for (i = 0; i < ARRAY_SIZE(reg_list); i++) { + err = imx274_write_reg(priv, reg_list[i].addr, + reg_list[i].val); + if (err) + goto fail; + } + + return 0; + +fail: + dev_err(&priv->client->dev, "%s error = %d\n", __func__, err); + return err; +} + +/* + * imx274_set_frame_interval - Function called when setting frame interval + * @priv: Pointer to device structure + * @frame_interval: Variable for frame interval + * + * Change frame interval by updating VMAX value + * The caller should hold the mutex lock imx274->lock if necessary + * + * Return: 0 on success + */ +static int imx274_set_frame_interval(struct stimx274 *priv, + struct v4l2_fract frame_interval) +{ + int err; + u32 frame_length, req_frame_rate; + u16 svr; + u16 hmax; + u8 reg_val[2]; + + dev_dbg(&priv->client->dev, "%s: input frame interval = %d / %d", + __func__, frame_interval.numerator, + frame_interval.denominator); + + if (frame_interval.numerator == 0) { + err = -EINVAL; + goto fail; + } + + req_frame_rate = (u32)(frame_interval.denominator + / frame_interval.numerator); + + /* boundary check */ + if (req_frame_rate > max_frame_rate[priv->mode_index]) { + frame_interval.numerator = 1; + frame_interval.denominator = + max_frame_rate[priv->mode_index]; + } else if (req_frame_rate < IMX274_MIN_FRAME_RATE) { + frame_interval.numerator = 1; + frame_interval.denominator = IMX274_MIN_FRAME_RATE; + } + + /* + * VMAX = 1/frame_rate x 72M / (SVR+1) / HMAX + * frame_length (i.e. VMAX) = (frame_interval) x 72M /(SVR+1) / HMAX + */ + + /* SVR */ + err = imx274_read_reg(priv, IMX274_SVR_REG_LSB, ®_val[0]); + if (err) + goto fail; + err = imx274_read_reg(priv, IMX274_SVR_REG_MSB, ®_val[1]); + if (err) + goto fail; + svr = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0]; + dev_dbg(&priv->client->dev, + "%s : register SVR = %d\n", __func__, svr); + + /* HMAX */ + err = imx274_read_reg(priv, IMX274_HMAX_REG_LSB, ®_val[0]); + if (err) + goto fail; + err = imx274_read_reg(priv, IMX274_HMAX_REG_MSB, ®_val[1]); + if (err) + goto fail; + hmax = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0]; + dev_dbg(&priv->client->dev, + "%s : register HMAX = %d\n", __func__, hmax); + + if (hmax == 0 || frame_interval.denominator == 0) { + err = -EINVAL; + goto fail; + } + + frame_length = IMX274_PIXCLK_CONST1 / (svr + 1) / hmax + * frame_interval.numerator + / frame_interval.denominator; + + err = imx274_set_frame_length(priv, frame_length); + if (err) + goto fail; + + priv->frame_interval = frame_interval; + return 0; + +fail: + dev_err(&priv->client->dev, "%s error = %d\n", __func__, err); + return err; +} + +static const struct v4l2_subdev_pad_ops imx274_pad_ops = { + .get_fmt = imx274_get_fmt, + .set_fmt = imx274_set_fmt, +}; + +static const struct v4l2_subdev_video_ops imx274_video_ops = { + .g_frame_interval = imx274_g_frame_interval, + .s_frame_interval = imx274_s_frame_interval, + .s_stream = imx274_s_stream, +}; + +static const struct v4l2_subdev_ops imx274_subdev_ops = { + .pad = &imx274_pad_ops, + .video = &imx274_video_ops, +}; + +static const struct v4l2_ctrl_ops imx274_ctrl_ops = { + .s_ctrl = imx274_s_ctrl, +}; + +static const struct of_device_id imx274_of_id_table[] = { + { .compatible = "sony,imx274" }, + { } +}; +MODULE_DEVICE_TABLE(of, imx274_of_id_table); + +static const struct i2c_device_id imx274_id[] = { + { "IMX274", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, imx274_id); + +static int imx274_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct v4l2_subdev *sd; + struct stimx274 *imx274; + int ret; + + /* initialize imx274 */ + imx274 = devm_kzalloc(&client->dev, sizeof(*imx274), GFP_KERNEL); + if (!imx274) + return -ENOMEM; + + mutex_init(&imx274->lock); + + /* initialize regmap */ + imx274->regmap = devm_regmap_init_i2c(client, &imx274_regmap_config); + if (IS_ERR(imx274->regmap)) { + dev_err(&client->dev, + "regmap init failed: %ld\n", PTR_ERR(imx274->regmap)); + ret = -ENODEV; + goto err_regmap; + } + + /* initialize subdevice */ + imx274->client = client; + sd = &imx274->sd; + v4l2_i2c_subdev_init(sd, client, &imx274_subdev_ops); + strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + + /* initialize subdev media pad */ + imx274->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&sd->entity, 1, &imx274->pad); + if (ret < 0) { + dev_err(&client->dev, + "%s : media entity init Failed %d\n", __func__, ret); + goto err_regmap; + } + + /* initialize sensor reset gpio */ + imx274->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(imx274->reset_gpio)) { + if (PTR_ERR(imx274->reset_gpio) != -EPROBE_DEFER) + dev_err(&client->dev, "Reset GPIO not setup in DT"); + ret = PTR_ERR(imx274->reset_gpio); + goto err_me; + } + + /* pull sensor out of reset */ + imx274_reset(imx274, 1); + + /* initialize controls */ + ret = v4l2_ctrl_handler_init(&imx274->ctrls.handler, 2); + if (ret < 0) { + dev_err(&client->dev, + "%s : ctrl handler init Failed\n", __func__); + goto err_me; + } + + imx274->ctrls.handler.lock = &imx274->lock; + + /* add new controls */ + imx274->ctrls.test_pattern = v4l2_ctrl_new_std_menu_items( + &imx274->ctrls.handler, &imx274_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(tp_qmenu) - 1, 0, 0, tp_qmenu); + + imx274->ctrls.gain = v4l2_ctrl_new_std( + &imx274->ctrls.handler, + &imx274_ctrl_ops, + V4L2_CID_GAIN, IMX274_MIN_GAIN, + IMX274_MAX_DIGITAL_GAIN * IMX274_MAX_ANALOG_GAIN, 1, + IMX274_DEF_GAIN); + + imx274->ctrls.exposure = v4l2_ctrl_new_std( + &imx274->ctrls.handler, + &imx274_ctrl_ops, + V4L2_CID_EXPOSURE, IMX274_MIN_EXPOSURE_TIME, + 1000000 / IMX274_DEF_FRAME_RATE, 1, + IMX274_MIN_EXPOSURE_TIME); + + imx274->ctrls.vflip = v4l2_ctrl_new_std( + &imx274->ctrls.handler, + &imx274_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + imx274->sd.ctrl_handler = &imx274->ctrls.handler; + if (imx274->ctrls.handler.error) { + ret = imx274->ctrls.handler.error; + goto err_ctrls; + } + + /* setup default controls */ + ret = v4l2_ctrl_handler_setup(&imx274->ctrls.handler); + if (ret) { + dev_err(&client->dev, + "Error %d setup default controls\n", ret); + goto err_ctrls; + } + + /* initialize format */ + imx274->mode_index = IMX274_MODE_3840X2160; + imx274->format.width = imx274_formats[0].size.width; + imx274->format.height = imx274_formats[0].size.height; + imx274->format.field = V4L2_FIELD_NONE; + imx274->format.code = MEDIA_BUS_FMT_SRGGB10_1X10; + imx274->format.colorspace = V4L2_COLORSPACE_SRGB; + imx274->frame_interval.numerator = 1; + imx274->frame_interval.denominator = IMX274_DEF_FRAME_RATE; + + /* load default control values */ + ret = imx274_load_default(imx274); + if (ret) { + dev_err(&client->dev, + "%s : imx274_load_default failed %d\n", + __func__, ret); + goto err_ctrls; + } + + /* register subdevice */ + ret = v4l2_async_register_subdev(sd); + if (ret < 0) { + dev_err(&client->dev, + "%s : v4l2_async_register_subdev failed %d\n", + __func__, ret); + goto err_ctrls; + } + + dev_info(&client->dev, "imx274 : imx274 probe success !\n"); + return 0; + +err_ctrls: + v4l2_ctrl_handler_free(&imx274->ctrls.handler); +err_me: + media_entity_cleanup(&sd->entity); +err_regmap: + mutex_destroy(&imx274->lock); + return ret; +} + +static int imx274_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct stimx274 *imx274 = to_imx274(sd); + + /* stop stream */ + imx274_write_table(imx274, mode_table[IMX274_MODE_STOP_STREAM]); + + v4l2_async_unregister_subdev(sd); + v4l2_ctrl_handler_free(&imx274->ctrls.handler); + media_entity_cleanup(&sd->entity); + mutex_destroy(&imx274->lock); + return 0; +} + +static struct i2c_driver imx274_i2c_driver = { + .driver = { + .name = DRIVER_NAME, + .of_match_table = imx274_of_id_table, + }, + .probe = imx274_probe, + .remove = imx274_remove, + .id_table = imx274_id, +}; + +module_i2c_driver(imx274_i2c_driver); + +MODULE_AUTHOR("Leon Luo <leonl@leopardimaging.com>"); +MODULE_DESCRIPTION("IMX274 CMOS Image Sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index a374e2a0ac3d..8b5f7d0435e4 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -460,7 +460,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) */ rc->map_name = ir->ir_codes; rc->allowed_protocols = rc_proto; - rc->enabled_protocols = rc_proto; if (!rc->driver_name) rc->driver_name = MODULE_NAME; diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c index 251a2aaf98c3..b600e03aa94b 100644 --- a/drivers/media/i2c/lm3560.c +++ b/drivers/media/i2c/lm3560.c @@ -50,6 +50,7 @@ enum led_enable { /** * struct lm3560_flash * + * @dev: pointer to &struct device * @pdata: platform data * @regmap: reg. map for i2c * @lock: muxtex for serial access. diff --git a/drivers/media/i2c/m5mols/m5mols_capture.c b/drivers/media/i2c/m5mols/m5mols_capture.c index a0cd6dc32eb0..0fb457f57995 100644 --- a/drivers/media/i2c/m5mols/m5mols_capture.c +++ b/drivers/media/i2c/m5mols/m5mols_capture.c @@ -33,6 +33,10 @@ /** * m5mols_read_rational - I2C read of a rational number + * @sd: sub-device, as pointed by struct v4l2_subdev + * @addr_num: numerator register + * @addr_den: denominator register + * @val: place to store the division result * * Read numerator and denominator from registers @addr_num and @addr_den * respectively and return the division result in @val. @@ -53,6 +57,7 @@ static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num, /** * m5mols_capture_info - Gather captured image information + * @info: M-5MOLS driver data structure * * For now it gathers only EXIF information and file size. */ diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c index c2218c0a9e6f..82eab7c2bc8c 100644 --- a/drivers/media/i2c/m5mols/m5mols_controls.c +++ b/drivers/media/i2c/m5mols/m5mols_controls.c @@ -126,6 +126,7 @@ static struct m5mols_scenemode m5mols_default_scenemode[] = { /** * m5mols_do_scenemode() - Change current scenemode + * @info: M-5MOLS driver data structure * @mode: Desired mode of the scenemode * * WARNING: The execution order is important. Do not change the order. diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 463534d44756..12e79f9e32d5 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -114,7 +114,8 @@ static const struct m5mols_resolution m5mols_reg_res[] = { /** * m5mols_swap_byte - an byte array to integer conversion function - * @size: size in bytes of I2C packet defined in the M-5MOLS datasheet + * @data: byte array + * @length: size in bytes of I2C packet defined in the M-5MOLS datasheet * * Convert I2C data byte array with performing any required byte * reordering to assure proper values for each data type, regardless @@ -132,8 +133,9 @@ 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 + * @sd: sub-device, as pointed by struct v4l2_subdev * @size: desired size of I2C packet + * @reg: combination of size, category and command for the I2C packet * @val: read value * * Returns 0 on success, or else negative errno. @@ -232,6 +234,7 @@ int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val) /** * m5mols_write - I2C command write function + * @sd: sub-device, as pointed by struct v4l2_subdev * @reg: combination of size, category and command for the I2C packet * @val: value to write * @@ -284,6 +287,7 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) /** * m5mols_busy_wait - Busy waiting with I2C register polling + * @sd: sub-device, as pointed by struct v4l2_subdev * @reg: the I2C_REG() address of an 8-bit status register to check * @value: expected status register value * @mask: bit mask for the read status register value @@ -316,6 +320,8 @@ int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask, /** * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts + * @sd: sub-device, as pointed by struct v4l2_subdev + * @reg: combination of size, category and command for the I2C packet * * Before writing desired interrupt value the INT_FACTOR register should * be read to clear pending interrupts. @@ -349,6 +355,8 @@ int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 irq_mask, u32 timeout) /** * m5mols_reg_mode - Write the mode and check busy status + * @sd: sub-device, as pointed by struct v4l2_subdev + * @mode: the required operation mode * * It always accompanies a little delay changing the M-5MOLS mode, so it is * needed checking current busy status to guarantee right mode. @@ -364,6 +372,7 @@ static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode) /** * m5mols_set_mode - set the M-5MOLS controller mode + * @info: M-5MOLS driver data structure * @mode: the required operation mode * * The commands of M-5MOLS are grouped into specific modes. Each functionality @@ -421,6 +430,7 @@ int m5mols_set_mode(struct m5mols_info *info, u8 mode) /** * m5mols_get_version - retrieve full revisions information of M-5MOLS + * @sd: sub-device, as pointed by struct v4l2_subdev * * The version information includes revisions of hardware and firmware, * AutoFocus alghorithm version and the version string. @@ -489,6 +499,7 @@ static enum m5mols_restype __find_restype(u32 code) /** * __find_resolution - Lookup preset and type of M-5MOLS's resolution + * @sd: sub-device, as pointed by struct v4l2_subdev * @mf: pixel format to find/negotiate the resolution preset for * @type: M-5MOLS resolution type * @resolution: M-5MOLS resolution preset register value @@ -662,6 +673,7 @@ static const struct v4l2_subdev_pad_ops m5mols_pad_ops = { /** * m5mols_restore_controls - Apply current control values to the registers + * @info: M-5MOLS driver data structure * * m5mols_do_scenemode() handles all parameters for which there is yet no * individual control. It should be replaced at some point by setting each @@ -686,6 +698,7 @@ int m5mols_restore_controls(struct m5mols_info *info) /** * m5mols_start_monitor - Start the monitor mode + * @info: M-5MOLS driver data structure * * Before applying the controls setup the resolution and frame rate * in PARAMETER mode, and then switch over to MONITOR mode. @@ -789,6 +802,7 @@ int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd, /** * m5mols_fw_start - M-5MOLS internal ARM controller initialization + * @sd: sub-device, as pointed by struct v4l2_subdev * * Execute the M-5MOLS internal ARM controller initialization sequence. * This function should be called after the supply voltage has been @@ -844,6 +858,8 @@ static int m5mols_auto_focus_stop(struct m5mols_info *info) /** * m5mols_s_power - Main sensor power control function + * @sd: sub-device, as pointed by struct v4l2_subdev + * @on: if true, powers on the device; powers off otherwise. * * To prevent breaking the lens when the sensor is powered off the Soft-Landing * algorithm is called where available. The Soft-Landing algorithm availability diff --git a/drivers/media/i2c/max2175.c b/drivers/media/i2c/max2175.c index bf0e821a2b93..2f1966bdc473 100644 --- a/drivers/media/i2c/max2175.c +++ b/drivers/media/i2c/max2175.c @@ -1345,7 +1345,7 @@ static int max2175_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &max2175_ops); ctx->client = client; - sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; /* Controls */ hdl = &ctx->ctrl_hdl; diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c index 99b992e46702..b1665d97e0fd 100644 --- a/drivers/media/i2c/mt9m111.c +++ b/drivers/media/i2c/mt9m111.c @@ -945,7 +945,7 @@ static int mt9m111_probe(struct i2c_client *client, mt9m111->clk = v4l2_clk_get(&client->dev, "mclk"); if (IS_ERR(mt9m111->clk)) - return -EPROBE_DEFER; + return PTR_ERR(mt9m111->clk); /* Default HIGHPOWER context */ mt9m111->ctx = &context_b; diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c index af7af0d14c69..bf7d06f3f21a 100644 --- a/drivers/media/i2c/ov13858.c +++ b/drivers/media/i2c/ov13858.c @@ -104,7 +104,6 @@ struct ov13858_reg_list { /* Link frequency config */ struct ov13858_link_freq_config { - u32 pixel_rate; u32 pixels_per_line; /* PLL registers for this link frequency */ @@ -238,11 +237,11 @@ static const struct ov13858_reg mode_4224x3136_regs[] = { {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, - {0x3803, 0x00}, + {0x3803, 0x08}, {0x3804, 0x10}, {0x3805, 0x9f}, {0x3806, 0x0c}, - {0x3807, 0x5f}, + {0x3807, 0x57}, {0x3808, 0x10}, {0x3809, 0x80}, {0x380a, 0x0c}, @@ -948,6 +947,18 @@ static const char * const ov13858_test_pattern_menu[] = { #define OV13858_LINK_FREQ_INDEX_0 0 #define OV13858_LINK_FREQ_INDEX_1 1 +/* + * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample + * data rate => double data rate; number of lanes => 4; bits per pixel => 10 + */ +static u64 link_freq_to_pixel_rate(u64 f) +{ + f *= 2 * 4; + do_div(f, 10); + + return f; +} + /* Menu items for LINK_FREQ V4L2 control */ static const s64 link_freq_menu_items[OV13858_NUM_OF_LINK_FREQS] = { OV13858_LINK_FREQ_540MHZ, @@ -958,8 +969,6 @@ static const s64 link_freq_menu_items[OV13858_NUM_OF_LINK_FREQS] = { static const struct ov13858_link_freq_config link_freq_configs[OV13858_NUM_OF_LINK_FREQS] = { { - /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */ - .pixel_rate = (OV13858_LINK_FREQ_540MHZ * 2 * 4) / 10, .pixels_per_line = OV13858_PPL_540MHZ, .reg_list = { .num_of_regs = ARRAY_SIZE(mipi_data_rate_1080mbps), @@ -967,8 +976,6 @@ static const struct ov13858_link_freq_config } }, { - /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */ - .pixel_rate = (OV13858_LINK_FREQ_270MHZ * 2 * 4) / 10, .pixels_per_line = OV13858_PPL_270MHZ, .reg_list = { .num_of_regs = ARRAY_SIZE(mipi_data_rate_540mbps), @@ -1385,6 +1392,8 @@ ov13858_set_pad_format(struct v4l2_subdev *sd, s32 vblank_def; s32 vblank_min; s64 h_blank; + s64 pixel_rate; + s64 link_freq; mutex_lock(&ov13858->mutex); @@ -1400,9 +1409,10 @@ ov13858_set_pad_format(struct v4l2_subdev *sd, } else { ov13858->cur_mode = mode; __v4l2_ctrl_s_ctrl(ov13858->link_freq, mode->link_freq_index); - __v4l2_ctrl_s_ctrl_int64( - ov13858->pixel_rate, - link_freq_configs[mode->link_freq_index].pixel_rate); + link_freq = link_freq_menu_items[mode->link_freq_index]; + pixel_rate = link_freq_to_pixel_rate(link_freq); + __v4l2_ctrl_s_ctrl_int64(ov13858->pixel_rate, pixel_rate); + /* Update limits and set FPS to default */ vblank_def = ov13858->cur_mode->vts_def - ov13858->cur_mode->height; @@ -1617,6 +1627,10 @@ static int ov13858_init_controls(struct ov13858 *ov13858) s64 exposure_max; s64 vblank_def; s64 vblank_min; + s64 hblank; + s64 pixel_rate_min; + s64 pixel_rate_max; + const struct ov13858_mode *mode; int ret; ctrl_hdlr = &ov13858->ctrl_handler; @@ -1634,29 +1648,30 @@ static int ov13858_init_controls(struct ov13858 *ov13858) link_freq_menu_items); ov13858->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]); + pixel_rate_min = link_freq_to_pixel_rate(link_freq_menu_items[1]); /* By default, PIXEL_RATE is read only */ ov13858->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops, - V4L2_CID_PIXEL_RATE, 0, - link_freq_configs[0].pixel_rate, 1, - link_freq_configs[0].pixel_rate); + V4L2_CID_PIXEL_RATE, + pixel_rate_min, pixel_rate_max, + 1, pixel_rate_max); - vblank_def = ov13858->cur_mode->vts_def - ov13858->cur_mode->height; - vblank_min = ov13858->cur_mode->vts_min - ov13858->cur_mode->height; + mode = ov13858->cur_mode; + vblank_def = mode->vts_def - mode->height; + vblank_min = mode->vts_min - mode->height; ov13858->vblank = v4l2_ctrl_new_std( ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_VBLANK, - vblank_min, - OV13858_VTS_MAX - ov13858->cur_mode->height, 1, + vblank_min, OV13858_VTS_MAX - mode->height, 1, vblank_def); + hblank = link_freq_configs[mode->link_freq_index].pixels_per_line - + mode->width; ov13858->hblank = v4l2_ctrl_new_std( ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_HBLANK, - OV13858_PPL_540MHZ - ov13858->cur_mode->width, - OV13858_PPL_540MHZ - ov13858->cur_mode->width, - 1, - OV13858_PPL_540MHZ - ov13858->cur_mode->width); + hblank, hblank, 1, hblank); ov13858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; - exposure_max = ov13858->cur_mode->vts_def - 8; + exposure_max = mode->vts_def - 8; ov13858->exposure = v4l2_ctrl_new_std( ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_EXPOSURE, OV13858_EXPOSURE_MIN, @@ -1746,7 +1761,7 @@ static int ov13858_probe(struct i2c_client *client, goto error_handler_free; } - ret = v4l2_async_register_subdev(&ov13858->sd); + ret = v4l2_async_register_subdev_sensor_common(&ov13858->sd); if (ret < 0) goto error_media_entity; diff --git a/drivers/media/i2c/ov2640.c b/drivers/media/i2c/ov2640.c index e6d0c1f64f0b..518868388d65 100644 --- a/drivers/media/i2c/ov2640.c +++ b/drivers/media/i2c/ov2640.c @@ -685,7 +685,7 @@ static int ov2640_mask_set(struct i2c_client *client, static int ov2640_reset(struct i2c_client *client) { int ret; - const struct regval_list reset_seq[] = { + static const struct regval_list reset_seq[] = { {BANK_SEL, BANK_SEL_SENS}, {COM7, COM7_SRST}, ENDMARKER, @@ -1097,18 +1097,17 @@ static int ov2640_probe(struct i2c_client *client, return -EIO; } - priv = devm_kzalloc(&client->dev, sizeof(struct ov2640_priv), GFP_KERNEL); - if (!priv) { - dev_err(&adapter->dev, - "Failed to allocate memory for private data!\n"); + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - } if (client->dev.of_node) { priv->clk = devm_clk_get(&client->dev, "xvclk"); if (IS_ERR(priv->clk)) - return -EPROBE_DEFER; - clk_prepare_enable(priv->clk); + return PTR_ERR(priv->clk); + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; } ret = ov2640_probe_dt(client, priv); @@ -1116,7 +1115,7 @@ static int ov2640_probe(struct i2c_client *client, goto err_clk; v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops); - priv->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; v4l2_ctrl_handler_init(&priv->hdl, 2); v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 39a2269c0bee..c89ed6609738 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -2271,7 +2271,7 @@ static int ov5640_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&sensor->sd, client, &ov5640_subdev_ops); - sensor->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; sensor->pad.flags = MEDIA_PAD_FL_SOURCE; sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad); diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index 95ce90fdb876..da39c49de503 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -35,9 +35,18 @@ #define SENSOR_NAME "ov5647" -#define OV5647_SW_RESET 0x0103 -#define OV5647_REG_CHIPID_H 0x300A -#define OV5647_REG_CHIPID_L 0x300B +#define MIPI_CTRL00_CLOCK_LANE_GATE BIT(5) +#define MIPI_CTRL00_BUS_IDLE BIT(2) +#define MIPI_CTRL00_CLOCK_LANE_DISABLE BIT(0) + +#define OV5647_SW_STANDBY 0x0100 +#define OV5647_SW_RESET 0x0103 +#define OV5647_REG_CHIPID_H 0x300A +#define OV5647_REG_CHIPID_L 0x300B +#define OV5640_REG_PAD_OUT 0x300D +#define OV5647_REG_FRAME_OFF_NUMBER 0x4202 +#define OV5647_REG_MIPI_CTRL00 0x4800 +#define OV5647_REG_MIPI_CTRL14 0x4814 #define REG_TERM 0xfffe #define VAL_TERM 0xfe @@ -241,34 +250,43 @@ static int ov5647_set_virtual_channel(struct v4l2_subdev *sd, int channel) u8 channel_id; int ret; - ret = ov5647_read(sd, 0x4814, &channel_id); + ret = ov5647_read(sd, OV5647_REG_MIPI_CTRL14, &channel_id); if (ret < 0) return ret; channel_id &= ~(3 << 6); - return ov5647_write(sd, 0x4814, channel_id | (channel << 6)); + return ov5647_write(sd, OV5647_REG_MIPI_CTRL14, channel_id | (channel << 6)); } static int ov5647_stream_on(struct v4l2_subdev *sd) { int ret; - ret = ov5647_write(sd, 0x4202, 0x00); + ret = ov5647_write(sd, OV5647_REG_MIPI_CTRL00, MIPI_CTRL00_BUS_IDLE); if (ret < 0) return ret; - return ov5647_write(sd, 0x300D, 0x00); + ret = ov5647_write(sd, OV5647_REG_FRAME_OFF_NUMBER, 0x00); + if (ret < 0) + return ret; + + return ov5647_write(sd, OV5640_REG_PAD_OUT, 0x00); } static int ov5647_stream_off(struct v4l2_subdev *sd) { int ret; - ret = ov5647_write(sd, 0x4202, 0x0f); + ret = ov5647_write(sd, OV5647_REG_MIPI_CTRL00, MIPI_CTRL00_CLOCK_LANE_GATE + | MIPI_CTRL00_BUS_IDLE | MIPI_CTRL00_CLOCK_LANE_DISABLE); if (ret < 0) return ret; - return ov5647_write(sd, 0x300D, 0x01); + ret = ov5647_write(sd, OV5647_REG_FRAME_OFF_NUMBER, 0x0f); + if (ret < 0) + return ret; + + return ov5647_write(sd, OV5640_REG_PAD_OUT, 0x01); } static int set_sw_standby(struct v4l2_subdev *sd, bool standby) @@ -276,7 +294,7 @@ static int set_sw_standby(struct v4l2_subdev *sd, bool standby) int ret; u8 rdval; - ret = ov5647_read(sd, 0x0100, &rdval); + ret = ov5647_read(sd, OV5647_SW_STANDBY, &rdval); if (ret < 0) return ret; @@ -285,7 +303,7 @@ static int set_sw_standby(struct v4l2_subdev *sd, bool standby) else rdval |= 0x01; - return ov5647_write(sd, 0x0100, rdval); + return ov5647_write(sd, OV5647_SW_STANDBY, rdval); } static int __sensor_init(struct v4l2_subdev *sd) @@ -294,7 +312,7 @@ static int __sensor_init(struct v4l2_subdev *sd) u8 resetval, rdval; struct i2c_client *client = v4l2_get_subdevdata(sd); - ret = ov5647_read(sd, 0x0100, &rdval); + ret = ov5647_read(sd, OV5647_SW_STANDBY, &rdval); if (ret < 0) return ret; @@ -309,18 +327,21 @@ static int __sensor_init(struct v4l2_subdev *sd) if (ret < 0) return ret; - ret = ov5647_read(sd, 0x0100, &resetval); + ret = ov5647_read(sd, OV5647_SW_STANDBY, &resetval); if (ret < 0) return ret; if (!(resetval & 0x01)) { dev_err(&client->dev, "Device was in SW standby"); - ret = ov5647_write(sd, 0x0100, 0x01); + ret = ov5647_write(sd, OV5647_SW_STANDBY, 0x01); if (ret < 0) return ret; } - return ov5647_write(sd, 0x4800, 0x04); + /* + * stream off to make the clock lane into LP-11 state. + */ + return ov5647_stream_off(sd); } static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) @@ -407,8 +428,8 @@ static int ov5647_sensor_set_register(struct v4l2_subdev *sd, } #endif -/** - * @short Subdev core operations registration +/* + * Subdev core operations registration */ static const struct v4l2_subdev_core_ops ov5647_subdev_core_ops = { .s_power = ov5647_sensor_power, diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c index 6f7a1d6d2200..9f9196568eb8 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -390,7 +390,10 @@ static const struct ov5670_reg mode_2592x1944_regs[] = { {0x5792, 0x00}, {0x5793, 0x52}, {0x5794, 0xa3}, - {0x3503, 0x00} + {0x3503, 0x00}, + {0x5045, 0x05}, + {0x4003, 0x40}, + {0x5048, 0x40} }; static const struct ov5670_reg mode_1296x972_regs[] = { @@ -653,7 +656,10 @@ static const struct ov5670_reg mode_1296x972_regs[] = { {0x5792, 0x00}, {0x5793, 0x52}, {0x5794, 0xa3}, - {0x3503, 0x00} + {0x3503, 0x00}, + {0x5045, 0x05}, + {0x4003, 0x40}, + {0x5048, 0x40} }; static const struct ov5670_reg mode_648x486_regs[] = { @@ -916,7 +922,10 @@ static const struct ov5670_reg mode_648x486_regs[] = { {0x5792, 0x00}, {0x5793, 0x52}, {0x5794, 0xa3}, - {0x3503, 0x00} + {0x3503, 0x00}, + {0x5045, 0x05}, + {0x4003, 0x40}, + {0x5048, 0x40} }; static const struct ov5670_reg mode_2560x1440_regs[] = { @@ -1178,7 +1187,10 @@ static const struct ov5670_reg mode_2560x1440_regs[] = { {0x5791, 0x06}, {0x5792, 0x00}, {0x5793, 0x52}, - {0x5794, 0xa3} + {0x5794, 0xa3}, + {0x5045, 0x05}, + {0x4003, 0x40}, + {0x5048, 0x40} }; static const struct ov5670_reg mode_1280x720_regs[] = { @@ -1441,7 +1453,10 @@ static const struct ov5670_reg mode_1280x720_regs[] = { {0x5792, 0x00}, {0x5793, 0x52}, {0x5794, 0xa3}, - {0x3503, 0x00} + {0x3503, 0x00}, + {0x5045, 0x05}, + {0x4003, 0x40}, + {0x5048, 0x40} }; static const struct ov5670_reg mode_640x360_regs[] = { @@ -1704,7 +1719,10 @@ static const struct ov5670_reg mode_640x360_regs[] = { {0x5792, 0x00}, {0x5793, 0x52}, {0x5794, 0xa3}, - {0x3503, 0x00} + {0x3503, 0x00}, + {0x5045, 0x05}, + {0x4003, 0x40}, + {0x5048, 0x40} }; static const char * const ov5670_test_pattern_menu[] = { @@ -2323,8 +2341,6 @@ static int ov5670_start_streaming(struct ov5670 *ov5670) return ret; } - ov5670->streaming = true; - return 0; } @@ -2338,8 +2354,6 @@ static int ov5670_stop_streaming(struct ov5670 *ov5670) if (ret) dev_err(&client->dev, "%s failed to set stream\n", __func__); - ov5670->streaming = false; - /* Return success even if it was an error, as there is nothing the * caller can do about it. */ @@ -2370,6 +2384,7 @@ static int ov5670_set_stream(struct v4l2_subdev *sd, int enable) ret = ov5670_stop_streaming(ov5670); pm_runtime_put(&client->dev); } + ov5670->streaming = enable; goto unlock_and_return; error: @@ -2514,7 +2529,7 @@ static int ov5670_probe(struct i2c_client *client) } /* Async register for subdev */ - ret = v4l2_async_register_subdev(&ov5670->sd); + ret = v4l2_async_register_subdev_sensor_common(&ov5670->sd); if (ret < 0) { err_msg = "v4l2_async_register_subdev() error"; goto error_entity_cleanup; diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c index 768f2950ea36..8975d16b2b24 100644 --- a/drivers/media/i2c/ov6650.c +++ b/drivers/media/i2c/ov6650.c @@ -951,11 +951,8 @@ static int ov6650_probe(struct i2c_client *client, int ret; priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&client->dev, - "Failed to allocate memory for private data!\n"); + if (!priv) return -ENOMEM; - } v4l2_i2c_subdev_init(&priv->subdev, client, &ov6650_subdev_ops); v4l2_ctrl_handler_init(&priv->hdl, 13); diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index e88549f0e704..950a0acf85fb 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -213,6 +213,9 @@ struct ov7670_devtype { struct ov7670_format_struct; /* coming later */ struct ov7670_info { struct v4l2_subdev sd; +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_pad pad; +#endif struct v4l2_ctrl_handler hdl; struct { /* gain cluster */ @@ -229,6 +232,7 @@ struct ov7670_info { struct v4l2_ctrl *saturation; struct v4l2_ctrl *hue; }; + struct v4l2_mbus_framefmt format; struct ov7670_format_struct *fmt; /* Current format */ struct clk *clk; struct gpio_desc *resetb_gpio; @@ -972,6 +976,9 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, fmt->width = wsize->width; fmt->height = wsize->height; fmt->colorspace = ov7670_formats[index].colorspace; + + info->format = *fmt; + return 0; } @@ -985,6 +992,9 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, struct ov7670_format_struct *ovfmt; struct ov7670_win_size *wsize; struct ov7670_info *info = to_state(sd); +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + struct v4l2_mbus_framefmt *mbus_fmt; +#endif unsigned char com7; int ret; @@ -995,8 +1005,13 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL); if (ret) return ret; - cfg->try_fmt = format->format; +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); + *mbus_fmt = format->format; return 0; +#else + return -ENOTTY; +#endif } ret = ov7670_try_fmt_internal(sd, &format->format, &ovfmt, &wsize); @@ -1038,6 +1053,30 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, return 0; } +static int ov7670_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct ov7670_info *info = to_state(sd); +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + struct v4l2_mbus_framefmt *mbus_fmt; +#endif + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, 0); + format->format = *mbus_fmt; + return 0; +#else + return -ENOTTY; +#endif + } else { + format->format = info->format; + } + + return 0; +} + /* * Implement G/S_PARM. There is a "high quality" mode we could try * to do someday; for now, we just do the frame rate tweak. @@ -1505,6 +1544,46 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static int ov7670_s_power(struct v4l2_subdev *sd, int on) +{ + struct ov7670_info *info = to_state(sd); + + if (info->pwdn_gpio) + gpiod_set_value(info->pwdn_gpio, !on); + if (on && info->resetb_gpio) { + gpiod_set_value(info->resetb_gpio, 1); + usleep_range(500, 1000); + gpiod_set_value(info->resetb_gpio, 0); + usleep_range(3000, 5000); + } + + return 0; +} + +static void ov7670_get_default_format(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *format) +{ + struct ov7670_info *info = to_state(sd); + + format->width = info->devtype->win_sizes[0].width; + format->height = info->devtype->win_sizes[0].height; + format->colorspace = info->fmt->colorspace; + format->code = info->fmt->mbus_code; + format->field = V4L2_FIELD_NONE; +} + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_mbus_framefmt *format = + v4l2_subdev_get_try_format(sd, fh->pad, 0); + + ov7670_get_default_format(sd, format); + + return 0; +} +#endif + /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1525,6 +1604,7 @@ static const struct v4l2_subdev_pad_ops ov7670_pad_ops = { .enum_frame_interval = ov7670_enum_frame_interval, .enum_frame_size = ov7670_enum_frame_size, .enum_mbus_code = ov7670_enum_mbus_code, + .get_fmt = ov7670_get_fmt, .set_fmt = ov7670_set_fmt, }; @@ -1534,6 +1614,12 @@ static const struct v4l2_subdev_ops ov7670_ops = { .pad = &ov7670_pad_ops, }; +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops ov7670_subdev_internal_ops = { + .open = ov7670_open, +}; +#endif + /* ----------------------------------------------------------------------- */ static const struct ov7670_devtype ov7670_devdata[] = { @@ -1586,6 +1672,11 @@ static int ov7670_probe(struct i2c_client *client, sd = &info->sd; v4l2_i2c_subdev_init(sd, client, &ov7670_ops); +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + sd->internal_ops = &ov7670_subdev_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; +#endif + info->clock_speed = 30; /* default: a guess */ if (client->dev.platform_data) { struct ov7670_config *config = client->dev.platform_data; @@ -1619,29 +1710,34 @@ static int ov7670_probe(struct i2c_client *client, if (ret) return ret; - ret = ov7670_init_gpio(client, info); - if (ret) - goto clk_disable; - info->clock_speed = clk_get_rate(info->clk) / 1000000; if (info->clock_speed < 10 || info->clock_speed > 48) { ret = -EINVAL; goto clk_disable; } + ret = ov7670_init_gpio(client, info); + if (ret) + goto clk_disable; + + ov7670_s_power(sd, 1); + /* Make sure it's an ov7670 */ ret = ov7670_detect(sd); if (ret) { v4l_dbg(1, debug, client, "chip found @ 0x%x (%s) is not an ov7670 chip.\n", client->addr << 1, client->adapter->name); - goto clk_disable; + goto power_off; } v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); info->devtype = &ov7670_devdata[id->driver_data]; info->fmt = &ov7670_formats[0]; + + ov7670_get_default_format(sd, &info->format); + info->clkrc = 0; /* Set default frame rate to 30 fps */ @@ -1688,16 +1784,31 @@ static int ov7670_probe(struct i2c_client *client, v4l2_ctrl_auto_cluster(2, &info->auto_exposure, V4L2_EXPOSURE_MANUAL, false); v4l2_ctrl_cluster(2, &info->saturation); + +#if defined(CONFIG_MEDIA_CONTROLLER) + info->pad.flags = MEDIA_PAD_FL_SOURCE; + info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); + if (ret < 0) + goto hdl_free; +#endif + v4l2_ctrl_handler_setup(&info->hdl); ret = v4l2_async_register_subdev(&info->sd); if (ret < 0) - goto hdl_free; + goto entity_cleanup; return 0; +entity_cleanup: +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&info->sd.entity); +#endif hdl_free: v4l2_ctrl_handler_free(&info->hdl); +power_off: + ov7670_s_power(sd, 0); clk_disable: clk_disable_unprepare(info->clk); return ret; @@ -1712,6 +1823,10 @@ static int ov7670_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); clk_disable_unprepare(info->clk); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&info->sd.entity); +#endif + ov7670_s_power(sd, 0); return 0; } diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index 6ffb460e8589..69433e1e2533 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -985,7 +985,6 @@ static const struct v4l2_ctrl_ops ov965x_ctrl_ops = { static const char * const test_pattern_menu[] = { "Disabled", "Color bars", - NULL }; static int ov965x_initialize_controls(struct ov965x *ov965x) diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c index 67dcca76f981..2e140272794b 100644 --- a/drivers/media/i2c/s5k6a3.c +++ b/drivers/media/i2c/s5k6a3.c @@ -53,6 +53,9 @@ enum { * @gpio_reset: GPIO connected to the sensor's reset pin * @lock: mutex protecting the structure's members below * @format: media bus format at the sensor's source pad + * @clock: pointer to &struct clk. + * @clock_frequency: clock frequency + * @power_count: stores state if device is powered */ struct s5k6a3 { struct device *dev; diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index 9fd254a8e20d..13c10b5e2b45 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c @@ -421,6 +421,7 @@ static int s5k6aa_set_ahb_address(struct i2c_client *client) /** * s5k6aa_configure_pixel_clock - apply ISP main clock/PLL configuration + * @s5k6aa: pointer to &struct s5k6aa describing the device * * Configure the internal ISP PLL for the required output frequency. * Locking: called with s5k6aa.lock mutex held. @@ -669,6 +670,7 @@ static int s5k6aa_set_input_params(struct s5k6aa *s5k6aa) /** * s5k6aa_configure_video_bus - configure the video output interface + * @s5k6aa: pointer to &struct s5k6aa describing the device * @bus_type: video bus type: parallel or MIPI-CSI * @nlanes: number of MIPI lanes to be used (MIPI-CSI only) * @@ -724,6 +726,8 @@ static int s5k6aa_new_config_sync(struct i2c_client *client, int timeout, /** * s5k6aa_set_prev_config - write user preview register set + * @s5k6aa: pointer to &struct s5k6aa describing the device + * @preset: s5kaa preset to be applied * * Configure output resolution and color fromat, pixel clock * frequency range, device frame rate type and frame period range. @@ -777,6 +781,7 @@ static int s5k6aa_set_prev_config(struct s5k6aa *s5k6aa, /** * s5k6aa_initialize_isp - basic ISP MCU initialization + * @sd: pointer to V4L2 sub-device descriptor * * Configure AHB addresses for registers read/write; configure PLLs for * required output pixel clock. The ISP power supply needs to be already diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 700f433261d0..e6b717b83b18 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -1239,6 +1239,10 @@ static int smiapp_power_on(struct device *dev) sleep = SMIAPP_RESET_DELAY(sensor->hwcfg->ext_clk); usleep_range(sleep, sleep); + mutex_lock(&sensor->mutex); + + sensor->active = true; + /* * Failures to respond to the address change command have been noticed. * Those failures seem to be caused by the sensor requiring a longer @@ -1313,7 +1317,7 @@ static int smiapp_power_on(struct device *dev) rval = smiapp_write(sensor, SMIAPP_REG_U8_DPHY_CTRL, SMIAPP_DPHY_CTRL_UI); if (rval < 0) - return rval; + goto out_cci_addr_fail; rval = smiapp_call_quirk(sensor, post_poweron); if (rval) { @@ -1321,28 +1325,28 @@ static int smiapp_power_on(struct device *dev) goto out_cci_addr_fail; } - /* Are we still initialising...? If yes, return here. */ - if (!sensor->pixel_array) - return 0; + /* Are we still initialising...? If not, proceed with control setup. */ + if (sensor->pixel_array) { + rval = __v4l2_ctrl_handler_setup( + &sensor->pixel_array->ctrl_handler); + if (rval) + goto out_cci_addr_fail; - rval = v4l2_ctrl_handler_setup(&sensor->pixel_array->ctrl_handler); - if (rval) - goto out_cci_addr_fail; + rval = __v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler); + if (rval) + goto out_cci_addr_fail; - rval = v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler); - if (rval) - goto out_cci_addr_fail; + rval = smiapp_update_mode(sensor); + if (rval < 0) + goto out_cci_addr_fail; + } - mutex_lock(&sensor->mutex); - rval = smiapp_update_mode(sensor); mutex_unlock(&sensor->mutex); - if (rval < 0) - goto out_cci_addr_fail; return 0; out_cci_addr_fail: - + mutex_unlock(&sensor->mutex); gpiod_set_value(sensor->xshutdown, 0); clk_disable_unprepare(sensor->ext_clk); @@ -1360,6 +1364,8 @@ static int smiapp_power_off(struct device *dev) struct smiapp_sensor *sensor = container_of(ssd, struct smiapp_sensor, ssds[0]); + mutex_lock(&sensor->mutex); + /* * Currently power/clock to lens are enable/disabled separately * but they are essentially the same signals. So if the sensor is @@ -1372,6 +1378,10 @@ static int smiapp_power_off(struct device *dev) SMIAPP_REG_U8_SOFTWARE_RESET, SMIAPP_SOFTWARE_RESET); + sensor->active = false; + + mutex_unlock(&sensor->mutex); + gpiod_set_value(sensor->xshutdown, 0); clk_disable_unprepare(sensor->ext_clk); usleep_range(5000, 5000); @@ -1381,29 +1391,6 @@ static int smiapp_power_off(struct device *dev) return 0; } -static int smiapp_set_power(struct v4l2_subdev *subdev, int on) -{ - int rval; - - if (!on) { - pm_runtime_mark_last_busy(subdev->dev); - pm_runtime_put_autosuspend(subdev->dev); - - return 0; - } - - rval = pm_runtime_get_sync(subdev->dev); - if (rval >= 0) - return 0; - - if (rval != -EBUSY && rval != -EAGAIN) - pm_runtime_set_active(subdev->dev); - - pm_runtime_put(subdev->dev); - - return rval; -} - /* ----------------------------------------------------------------------------- * Video stream management */ @@ -1560,19 +1547,31 @@ out: static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable) { struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); int rval; if (sensor->streaming == enable) return 0; if (enable) { + rval = pm_runtime_get_sync(&client->dev); + if (rval < 0) { + if (rval != -EBUSY && rval != -EAGAIN) + pm_runtime_set_active(&client->dev); + pm_runtime_put(&client->dev); + return rval; + } + sensor->streaming = true; + rval = smiapp_start_streaming(sensor); if (rval < 0) sensor->streaming = false; } else { rval = smiapp_stop_streaming(sensor); sensor->streaming = false; + pm_runtime_mark_last_busy(&client->dev); + pm_runtime_put_autosuspend(&client->dev); } return rval; @@ -2650,7 +2649,6 @@ static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) struct smiapp_subdev *ssd = to_smiapp_subdev(sd); struct smiapp_sensor *sensor = ssd->sensor; unsigned int i; - int rval; mutex_lock(&sensor->mutex); @@ -2677,22 +2675,6 @@ static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) mutex_unlock(&sensor->mutex); - rval = pm_runtime_get_sync(sd->dev); - if (rval >= 0) - return 0; - - if (rval != -EBUSY && rval != -EAGAIN) - pm_runtime_set_active(sd->dev); - pm_runtime_put(sd->dev); - - return rval; -} - -static int smiapp_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - pm_runtime_mark_last_busy(sd->dev); - pm_runtime_put_autosuspend(sd->dev); - return 0; } @@ -2700,10 +2682,6 @@ static const struct v4l2_subdev_video_ops smiapp_video_ops = { .s_stream = smiapp_set_stream, }; -static const struct v4l2_subdev_core_ops smiapp_core_ops = { - .s_power = smiapp_set_power, -}; - static const struct v4l2_subdev_pad_ops smiapp_pad_ops = { .enum_mbus_code = smiapp_enum_mbus_code, .get_fmt = smiapp_get_format, @@ -2718,7 +2696,6 @@ static const struct v4l2_subdev_sensor_ops smiapp_sensor_ops = { }; static const struct v4l2_subdev_ops smiapp_ops = { - .core = &smiapp_core_ops, .video = &smiapp_video_ops, .pad = &smiapp_pad_ops, .sensor = &smiapp_sensor_ops, @@ -2732,12 +2709,10 @@ static const struct v4l2_subdev_internal_ops smiapp_internal_src_ops = { .registered = smiapp_registered, .unregistered = smiapp_unregistered, .open = smiapp_open, - .close = smiapp_close, }; static const struct v4l2_subdev_internal_ops smiapp_internal_ops = { .open = smiapp_open, - .close = smiapp_close, }; /* ----------------------------------------------------------------------------- @@ -2829,12 +2804,10 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev) /* NVM size is not mandatory */ fwnode_property_read_u32(fwnode, "nokia,nvm-size", &hwcfg->nvm_size); - rval = fwnode_property_read_u32(fwnode, "clock-frequency", + rval = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", &hwcfg->ext_clk); - if (rval) { - dev_warn(dev, "can't get clock-frequency\n"); - goto out_err; - } + if (rval) + dev_info(dev, "can't get clock-frequency\n"); dev_dbg(dev, "nvm %d, clk %d, mode %d\n", hwcfg->nvm_size, hwcfg->ext_clk, hwcfg->csi_signalling_mode); @@ -2894,18 +2867,46 @@ static int smiapp_probe(struct i2c_client *client, } sensor->ext_clk = devm_clk_get(&client->dev, NULL); - if (IS_ERR(sensor->ext_clk)) { + if (PTR_ERR(sensor->ext_clk) == -ENOENT) { + dev_info(&client->dev, "no clock defined, continuing...\n"); + sensor->ext_clk = NULL; + } else if (IS_ERR(sensor->ext_clk)) { dev_err(&client->dev, "could not get clock (%ld)\n", PTR_ERR(sensor->ext_clk)); return -EPROBE_DEFER; } - rval = clk_set_rate(sensor->ext_clk, sensor->hwcfg->ext_clk); - if (rval < 0) { - dev_err(&client->dev, - "unable to set clock freq to %u\n", + if (sensor->ext_clk) { + if (sensor->hwcfg->ext_clk) { + unsigned long rate; + + rval = clk_set_rate(sensor->ext_clk, + sensor->hwcfg->ext_clk); + if (rval < 0) { + dev_err(&client->dev, + "unable to set clock freq to %u\n", + sensor->hwcfg->ext_clk); + return rval; + } + + rate = clk_get_rate(sensor->ext_clk); + if (rate != sensor->hwcfg->ext_clk) { + dev_err(&client->dev, + "can't set clock freq, asked for %u but got %lu\n", + sensor->hwcfg->ext_clk, rate); + return rval; + } + } else { + sensor->hwcfg->ext_clk = clk_get_rate(sensor->ext_clk); + dev_dbg(&client->dev, "obtained clock freq %u\n", + sensor->hwcfg->ext_clk); + } + } else if (sensor->hwcfg->ext_clk) { + dev_dbg(&client->dev, "assuming clock freq %u\n", sensor->hwcfg->ext_clk); - return rval; + } else { + dev_err(&client->dev, "unable to obtain clock freq\n"); + return -EINVAL; } sensor->xshutdown = devm_gpiod_get_optional(&client->dev, "xshutdown", @@ -3092,7 +3093,7 @@ static int smiapp_probe(struct i2c_client *client, if (rval < 0) goto out_media_entity_cleanup; - rval = v4l2_async_register_subdev(&sensor->src->sd); + rval = v4l2_async_register_subdev_sensor_common(&sensor->src->sd); if (rval < 0) goto out_media_entity_cleanup; diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c index d6779e35d36f..145653dc81da 100644 --- a/drivers/media/i2c/smiapp/smiapp-regs.c +++ b/drivers/media/i2c/smiapp/smiapp-regs.c @@ -231,6 +231,9 @@ int smiapp_write_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val) len != SMIAPP_REG_32BIT) || flags) return -EINVAL; + if (!sensor->active) + return 0; + msg.addr = client->addr; msg.flags = 0; /* Write */ msg.len = 2 + len; diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h index f74d695018b9..e6a5ab402d7f 100644 --- a/drivers/media/i2c/smiapp/smiapp.h +++ b/drivers/media/i2c/smiapp/smiapp.h @@ -206,6 +206,7 @@ struct smiapp_sensor { u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */ u8 frame_skip; + bool active; /* is the sensor powered on? */ u16 embedded_start; /* embedded data start line */ u16 embedded_end; u16 image_start; /* image data start line */ diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c index 0146d1f7aacb..c63948989688 100644 --- a/drivers/media/i2c/soc_camera/ov9640.c +++ b/drivers/media/i2c/soc_camera/ov9640.c @@ -335,8 +335,8 @@ static void ov9640_res_roundup(u32 *width, u32 *height) { int i; enum { QQCIF, QQVGA, QCIF, QVGA, CIF, VGA, SXGA }; - int res_x[] = { 88, 160, 176, 320, 352, 640, 1280 }; - int res_y[] = { 72, 120, 144, 240, 288, 480, 960 }; + static const int res_x[] = { 88, 160, 176, 320, 352, 640, 1280 }; + static const int res_y[] = { 72, 120, 144, 240, 288, 480, 960 }; for (i = 0; i < ARRAY_SIZE(res_x); i++) { if (res_x[i] >= *width && res_y[i] >= *height) { @@ -675,12 +675,9 @@ static int ov9640_probe(struct i2c_client *client, return -EINVAL; } - priv = devm_kzalloc(&client->dev, sizeof(struct ov9640_priv), GFP_KERNEL); - if (!priv) { - dev_err(&client->dev, - "Failed to allocate memory for private data!\n"); + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - } v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops); diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c index cc07b7ae5407..755de2289c39 100644 --- a/drivers/media/i2c/soc_camera/ov9740.c +++ b/drivers/media/i2c/soc_camera/ov9740.c @@ -935,11 +935,9 @@ static int ov9740_probe(struct i2c_client *client, return -EINVAL; } - priv = devm_kzalloc(&client->dev, sizeof(struct ov9740_priv), GFP_KERNEL); - if (!priv) { - dev_err(&client->dev, "Failed to allocate private data!\n"); + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - } v4l2_i2c_subdev_init(&priv->subdev, client, &ov9740_subdev_ops); v4l2_ctrl_handler_init(&priv->hdl, 13); diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index e6f5c363ccab..2b8181469b93 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -39,6 +39,7 @@ #include <linux/workqueue.h> #include <linux/v4l2-dv-timings.h> #include <linux/hdmi.h> +#include <media/cec.h> #include <media/v4l2-dv-timings.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> @@ -63,6 +64,7 @@ MODULE_LICENSE("GPL"); #define I2C_MAX_XFER_SIZE (EDID_BLOCK_SIZE + 2) +#define POLL_INTERVAL_CEC_MS 10 #define POLL_INTERVAL_MS 1000 static const struct v4l2_dv_timings_cap tc358743_timings_cap = { @@ -106,6 +108,8 @@ struct tc358743_state { u8 csi_lanes_in_use; struct gpio_desc *reset_gpio; + + struct cec_adapter *cec_adap; }; static void tc358743_enable_interrupts(struct v4l2_subdev *sd, @@ -595,6 +599,7 @@ static void tc358743_set_ref_clk(struct v4l2_subdev *sd) struct tc358743_platform_data *pdata = &state->pdata; u32 sys_freq; u32 lockdet_ref; + u32 cec_freq; u16 fh_min; u16 fh_max; @@ -626,6 +631,15 @@ static void tc358743_set_ref_clk(struct v4l2_subdev *sd) i2c_wr8_and_or(sd, NCO_F0_MOD, ~MASK_NCO_F0_MOD, (pdata->refclk_hz == 27000000) ? MASK_NCO_F0_MOD_27MHZ : 0x0); + + /* + * Trial and error suggests that the default register value + * of 656 is for a 42 MHz reference clock. Use that to derive + * a new value based on the actual reference clock. + */ + cec_freq = (656 * sys_freq) / 4200; + i2c_wr16(sd, CECHCLK, cec_freq); + i2c_wr16(sd, CECLCLK, cec_freq); } static void tc358743_set_csi_color_space(struct v4l2_subdev *sd) @@ -814,11 +828,17 @@ static void tc358743_initial_setup(struct v4l2_subdev *sd) struct tc358743_state *state = to_state(sd); struct tc358743_platform_data *pdata = &state->pdata; - /* CEC and IR are not supported by this driver */ - i2c_wr16_and_or(sd, SYSCTL, ~(MASK_CECRST | MASK_IRRST), - (MASK_CECRST | MASK_IRRST)); + /* + * IR is not supported by this driver. + * CEC is only enabled if needed. + */ + i2c_wr16_and_or(sd, SYSCTL, ~(MASK_IRRST | MASK_CECRST), + (MASK_IRRST | MASK_CECRST)); tc358743_reset(sd, MASK_CTXRST | MASK_HDMIRST); +#ifdef CONFIG_VIDEO_TC358743_CEC + tc358743_reset(sd, MASK_CECRST); +#endif tc358743_sleep_mode(sd, false); i2c_wr16(sd, FIFOCTL, pdata->fifo_level); @@ -842,6 +862,133 @@ static void tc358743_initial_setup(struct v4l2_subdev *sd) i2c_wr8(sd, VOUT_SET3, MASK_VOUT_EXTCNT); } +/* --------------- CEC --------------- */ + +#ifdef CONFIG_VIDEO_TC358743_CEC +static int tc358743_cec_adap_enable(struct cec_adapter *adap, bool enable) +{ + struct tc358743_state *state = adap->priv; + struct v4l2_subdev *sd = &state->sd; + + i2c_wr32(sd, CECIMSK, enable ? MASK_CECTIM | MASK_CECRIM : 0); + i2c_wr32(sd, CECICLR, MASK_CECTICLR | MASK_CECRICLR); + i2c_wr32(sd, CECEN, enable); + if (enable) + i2c_wr32(sd, CECREN, MASK_CECREN); + return 0; +} + +static int tc358743_cec_adap_monitor_all_enable(struct cec_adapter *adap, + bool enable) +{ + struct tc358743_state *state = adap->priv; + struct v4l2_subdev *sd = &state->sd; + u32 reg; + + reg = i2c_rd32(sd, CECRCTL1); + if (enable) + reg |= MASK_CECOTH; + else + reg &= ~MASK_CECOTH; + i2c_wr32(sd, CECRCTL1, reg); + return 0; +} + +static int tc358743_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) +{ + struct tc358743_state *state = adap->priv; + struct v4l2_subdev *sd = &state->sd; + unsigned int la = 0; + + if (log_addr != CEC_LOG_ADDR_INVALID) { + la = i2c_rd32(sd, CECADD); + la |= 1 << log_addr; + } + i2c_wr32(sd, CECADD, la); + return 0; +} + +static int tc358743_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time, struct cec_msg *msg) +{ + struct tc358743_state *state = adap->priv; + struct v4l2_subdev *sd = &state->sd; + unsigned int i; + + i2c_wr32(sd, CECTCTL, + (cec_msg_is_broadcast(msg) ? MASK_CECBRD : 0) | + (signal_free_time - 1)); + for (i = 0; i < msg->len; i++) + i2c_wr32(sd, CECTBUF1 + i * 4, + msg->msg[i] | ((i == msg->len - 1) ? MASK_CECTEOM : 0)); + i2c_wr32(sd, CECTEN, MASK_CECTEN); + return 0; +} + +static const struct cec_adap_ops tc358743_cec_adap_ops = { + .adap_enable = tc358743_cec_adap_enable, + .adap_log_addr = tc358743_cec_adap_log_addr, + .adap_transmit = tc358743_cec_adap_transmit, + .adap_monitor_all_enable = tc358743_cec_adap_monitor_all_enable, +}; + +static void tc358743_cec_isr(struct v4l2_subdev *sd, u16 intstatus, + bool *handled) +{ + struct tc358743_state *state = to_state(sd); + unsigned int cec_rxint, cec_txint; + unsigned int clr = 0; + + cec_rxint = i2c_rd32(sd, CECRSTAT); + cec_txint = i2c_rd32(sd, CECTSTAT); + + if (intstatus & MASK_CEC_RINT) + clr |= MASK_CECRICLR; + if (intstatus & MASK_CEC_TINT) + clr |= MASK_CECTICLR; + i2c_wr32(sd, CECICLR, clr); + + if ((intstatus & MASK_CEC_TINT) && cec_txint) { + if (cec_txint & MASK_CECTIEND) + cec_transmit_attempt_done(state->cec_adap, + CEC_TX_STATUS_OK); + else if (cec_txint & MASK_CECTIAL) + cec_transmit_attempt_done(state->cec_adap, + CEC_TX_STATUS_ARB_LOST); + else if (cec_txint & MASK_CECTIACK) + cec_transmit_attempt_done(state->cec_adap, + CEC_TX_STATUS_NACK); + else if (cec_txint & MASK_CECTIUR) { + /* + * Not sure when this bit is set. Treat + * it as an error for now. + */ + cec_transmit_attempt_done(state->cec_adap, + CEC_TX_STATUS_ERROR); + } + *handled = true; + } + if ((intstatus & MASK_CEC_RINT) && + (cec_rxint & MASK_CECRIEND)) { + struct cec_msg msg = {}; + unsigned int i; + unsigned int v; + + v = i2c_rd32(sd, CECRCTR); + msg.len = v & 0x1f; + for (i = 0; i < msg.len; i++) { + v = i2c_rd32(sd, CECRBUF1 + i * 4); + msg.msg[i] = v & 0xff; + } + cec_received_msg(state->cec_adap, &msg); + *handled = true; + } + i2c_wr16(sd, INTSTATUS, + intstatus & (MASK_CEC_RINT | MASK_CEC_TINT)); +} + +#endif + /* --------------- IRQ --------------- */ static void tc358743_format_change(struct v4l2_subdev *sd) @@ -1296,6 +1443,15 @@ static int tc358743_isr(struct v4l2_subdev *sd, u32 status, bool *handled) intstatus &= ~MASK_HDMI_INT; } +#ifdef CONFIG_VIDEO_TC358743_CEC + if (intstatus & (MASK_CEC_RINT | MASK_CEC_TINT)) { + tc358743_cec_isr(sd, intstatus, handled); + i2c_wr16(sd, INTSTATUS, + intstatus & (MASK_CEC_RINT | MASK_CEC_TINT)); + intstatus &= ~(MASK_CEC_RINT | MASK_CEC_TINT); + } +#endif + if (intstatus & MASK_CSI_INT) { u32 csi_int = i2c_rd32(sd, CSI_INT); @@ -1325,13 +1481,18 @@ static irqreturn_t tc358743_irq_handler(int irq, void *dev_id) return handled ? IRQ_HANDLED : IRQ_NONE; } -static void tc358743_irq_poll_timer(unsigned long arg) +static void tc358743_irq_poll_timer(struct timer_list *t) { - struct tc358743_state *state = (struct tc358743_state *)arg; + struct tc358743_state *state = from_timer(state, t, timer); + unsigned int msecs; schedule_work(&state->work_i2c_poll); - - mod_timer(&state->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS)); + /* + * If CEC is present, then we need to poll more frequently, + * otherwise we will miss CEC messages. + */ + msecs = state->cec_adap ? POLL_INTERVAL_CEC_MS : POLL_INTERVAL_MS; + mod_timer(&state->timer, jiffies + msecs_to_jiffies(msecs)); } static void tc358743_work_i2c_poll(struct work_struct *work) @@ -1488,7 +1649,7 @@ static int tc358743_s_stream(struct v4l2_subdev *sd, int enable) { enable_stream(sd, enable); if (!enable) { - /* Put all lanes in PL-11 state (STOPSTATE) */ + /* Put all lanes in LP-11 state (STOPSTATE) */ tc358743_set_csi(sd); } @@ -1621,6 +1782,8 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, { struct tc358743_state *state = to_state(sd); u16 edid_len = edid->blocks * EDID_BLOCK_SIZE; + u16 pa; + int err; int i; v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n", @@ -1638,6 +1801,12 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, edid->blocks = EDID_NUM_BLOCKS_MAX; return -E2BIG; } + pa = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, NULL); + err = cec_phys_addr_validate(pa, &pa, NULL); + if (err) + return err; + + cec_phys_addr_invalidate(state->cec_adap); tc358743_disable_edid(sd); @@ -1654,6 +1823,8 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, state->edid_blocks_written = edid->blocks; + cec_s_phys_addr(state->cec_adap, pa, false); + if (tx_5v_power_present(sd)) tc358743_enable_edid(sd); @@ -1770,6 +1941,11 @@ static int tc358743_probe_of(struct tc358743_state *state) goto free_endpoint; } + if (endpoint->bus.mipi_csi2.num_data_lanes > 4) { + dev_err(dev, "invalid number of lanes\n"); + goto free_endpoint; + } + state->bus = endpoint->bus.mipi_csi2; ret = clk_prepare_enable(refclk); @@ -1867,6 +2043,7 @@ static int tc358743_probe(struct i2c_client *client, struct tc358743_state *state; struct tc358743_platform_data *pdata = client->dev.platform_data; struct v4l2_subdev *sd; + u16 irq_mask = MASK_HDMI_MSK | MASK_CSI_MSK; int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -1929,6 +2106,7 @@ static int tc358743_probe(struct i2c_client *client, } state->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; err = media_entity_pads_init(&sd->entity, 1, &state->pad); if (err < 0) goto err_hdl; @@ -1945,6 +2123,17 @@ static int tc358743_probe(struct i2c_client *client, INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, tc358743_delayed_work_enable_hotplug); +#ifdef CONFIG_VIDEO_TC358743_CEC + state->cec_adap = cec_allocate_adapter(&tc358743_cec_adap_ops, + state, dev_name(&client->dev), + CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL, CEC_MAX_LOG_ADDRS); + if (IS_ERR(state->cec_adap)) { + err = PTR_ERR(state->cec_adap); + goto err_hdl; + } + irq_mask |= MASK_CEC_RMSK | MASK_CEC_TMSK; +#endif + tc358743_initial_setup(sd); tc358743_s_dv_timings(sd, &default_timing); @@ -1964,15 +2153,22 @@ static int tc358743_probe(struct i2c_client *client, } else { INIT_WORK(&state->work_i2c_poll, tc358743_work_i2c_poll); - state->timer.data = (unsigned long)state; - state->timer.function = tc358743_irq_poll_timer; + timer_setup(&state->timer, tc358743_irq_poll_timer, 0); state->timer.expires = jiffies + msecs_to_jiffies(POLL_INTERVAL_MS); add_timer(&state->timer); } + err = cec_register_adapter(state->cec_adap, &client->dev); + if (err < 0) { + pr_err("%s: failed to register the cec device\n", __func__); + cec_delete_adapter(state->cec_adap); + state->cec_adap = NULL; + goto err_work_queues; + } + tc358743_enable_interrupts(sd, tx_5v_power_present(sd)); - i2c_wr16(sd, INTMASK, ~(MASK_HDMI_MSK | MASK_CSI_MSK) & 0xffff); + i2c_wr16(sd, INTMASK, ~irq_mask); err = v4l2_ctrl_handler_setup(sd->ctrl_handler); if (err) @@ -1984,6 +2180,7 @@ static int tc358743_probe(struct i2c_client *client, return 0; err_work_queues: + cec_unregister_adapter(state->cec_adap); if (!state->i2c_client->irq) flush_work(&state->work_i2c_poll); cancel_delayed_work(&state->delayed_work_enable_hotplug); @@ -2004,6 +2201,7 @@ static int tc358743_remove(struct i2c_client *client) flush_work(&state->work_i2c_poll); } cancel_delayed_work(&state->delayed_work_enable_hotplug); + cec_unregister_adapter(state->cec_adap); v4l2_async_unregister_subdev(sd); v4l2_device_unregister_subdev(sd); mutex_destroy(&state->confctl_mutex); diff --git a/drivers/media/i2c/tc358743_regs.h b/drivers/media/i2c/tc358743_regs.h index 657ef50f215f..227b46471793 100644 --- a/drivers/media/i2c/tc358743_regs.h +++ b/drivers/media/i2c/tc358743_regs.h @@ -193,8 +193,98 @@ #define CSI_START 0x0518 #define MASK_STRT 0x00000001 -#define CECEN 0x0600 -#define MASK_CECEN 0x0001 +/* *** CEC (32 bit) *** */ +#define CECHCLK 0x0028 /* 16 bits */ +#define MASK_CECHCLK (0x7ff << 0) + +#define CECLCLK 0x002a /* 16 bits */ +#define MASK_CECLCLK (0x7ff << 0) + +#define CECEN 0x0600 +#define MASK_CECEN 0x0001 + +#define CECADD 0x0604 +#define CECRST 0x0608 +#define MASK_CECRESET 0x0001 + +#define CECREN 0x060c +#define MASK_CECREN 0x0001 + +#define CECRCTL1 0x0614 +#define MASK_CECACKDIS (1 << 24) +#define MASK_CECHNC (3 << 20) +#define MASK_CECLNC (7 << 16) +#define MASK_CECMIN (7 << 12) +#define MASK_CECMAX (7 << 8) +#define MASK_CECDAT (7 << 4) +#define MASK_CECTOUT (3 << 2) +#define MASK_CECRIHLD (1 << 1) +#define MASK_CECOTH (1 << 0) + +#define CECRCTL2 0x0618 +#define MASK_CECSWAV3 (7 << 12) +#define MASK_CECSWAV2 (7 << 8) +#define MASK_CECSWAV1 (7 << 4) +#define MASK_CECSWAV0 (7 << 0) + +#define CECRCTL3 0x061c +#define MASK_CECWAV3 (7 << 20) +#define MASK_CECWAV2 (7 << 16) +#define MASK_CECWAV1 (7 << 12) +#define MASK_CECWAV0 (7 << 8) +#define MASK_CECACKEI (1 << 4) +#define MASK_CECMINEI (1 << 3) +#define MASK_CECMAXEI (1 << 2) +#define MASK_CECRSTEI (1 << 1) +#define MASK_CECWAVEI (1 << 0) + +#define CECTEN 0x0620 +#define MASK_CECTBUSY (1 << 1) +#define MASK_CECTEN (1 << 0) + +#define CECTCTL 0x0628 +#define MASK_CECSTRS (7 << 20) +#define MASK_CECSPRD (7 << 16) +#define MASK_CECDTRS (7 << 12) +#define MASK_CECDPRD (15 << 8) +#define MASK_CECBRD (1 << 4) +#define MASK_CECFREE (15 << 0) + +#define CECRSTAT 0x062c +#define MASK_CECRIWA (1 << 6) +#define MASK_CECRIOR (1 << 5) +#define MASK_CECRIACK (1 << 4) +#define MASK_CECRIMIN (1 << 3) +#define MASK_CECRIMAX (1 << 2) +#define MASK_CECRISTA (1 << 1) +#define MASK_CECRIEND (1 << 0) + +#define CECTSTAT 0x0630 +#define MASK_CECTIUR (1 << 4) +#define MASK_CECTIACK (1 << 3) +#define MASK_CECTIAL (1 << 2) +#define MASK_CECTIEND (1 << 1) + +#define CECRBUF1 0x0634 +#define MASK_CECRACK (1 << 9) +#define MASK_CECEOM (1 << 8) +#define MASK_CECRBYTE (0xff << 0) + +#define CECTBUF1 0x0674 +#define MASK_CECTEOM (1 << 8) +#define MASK_CECTBYTE (0xff << 0) + +#define CECRCTR 0x06b4 +#define MASK_CECRCTR (0x1f << 0) + +#define CECIMSK 0x06c0 +#define MASK_CECTIM (1 << 1) +#define MASK_CECRIM (1 << 0) + +#define CECICLR 0x06cc +#define MASK_CECTICLR (1 << 1) +#define MASK_CECRICLR (1 << 0) + #define HDMI_INT0 0x8500 #define MASK_I_KEY 0x80 diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c index ce86534450ac..16a1e08ce06c 100644 --- a/drivers/media/i2c/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c @@ -300,9 +300,9 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) * if available, ... */ -static void chip_thread_wake(unsigned long data) +static void chip_thread_wake(struct timer_list *t) { - struct CHIPSTATE *chip = (struct CHIPSTATE*)data; + struct CHIPSTATE *chip = from_timer(chip, t, wt); wake_up_process(chip->thread); } @@ -1995,7 +1995,7 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * v4l2_ctrl_handler_setup(&chip->hdl); chip->thread = NULL; - init_timer(&chip->wt); + timer_setup(&chip->wt, chip_thread_wake, 0); if (desc->flags & CHIP_NEED_CHECKMODE) { if (!desc->getrxsubchans || !desc->setaudmode) { /* This shouldn't be happen. Warn user, but keep working @@ -2005,8 +2005,6 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * return 0; } /* start async thread */ - chip->wt.function = chip_thread_wake; - chip->wt.data = (unsigned long)chip; chip->thread = kthread_run(chip_thread, chip, "%s", client->name); if (IS_ERR(chip->thread)) { diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index ad2df998f9c5..d575b3e7e835 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -86,6 +86,7 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable); /** * struct tvp514x_decoder - TVP5146/47 decoder object * @sd: Subdevice Slave handle + * @hdl: embedded &struct v4l2_ctrl_handler * @tvp514x_regs: copy of hw's regs with preset values. * @pdata: Board specific * @ver: Chip version @@ -98,6 +99,9 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable); * @std_list: Standards list * @input: Input routing at chip level * @output: Output routing at chip level + * @pad: subdev media pad associated with the decoder + * @format: media bus frame format + * @int_seq: driver's register init sequence */ struct tvp514x_decoder { struct v4l2_subdev sd; @@ -211,7 +215,7 @@ static struct tvp514x_reg tvp514x_reg_list_default[] = { {TOK_TERM, 0, 0}, }; -/** +/* * List of image formats supported by TVP5146/47 decoder * Currently we are using 8 bit mode only, but can be * extended to 10/20 bit mode. @@ -226,7 +230,7 @@ static const struct v4l2_fmtdesc tvp514x_fmt_list[] = { }, }; -/** +/* * Supported standards - * * Currently supports two standards only, need to add support for rest of the @@ -931,7 +935,7 @@ static int tvp514x_get_pad_format(struct v4l2_subdev *sd, * tvp514x_set_pad_format() - V4L2 decoder interface handler for set pad format * @sd: pointer to standard V4L2 sub-device structure * @cfg: pad configuration - * @format: pointer to v4l2_subdev_format structure + * @fmt: pointer to v4l2_subdev_format structure * * Set pad format for the output pad */ @@ -1199,7 +1203,7 @@ static const struct tvp514x_reg tvp514xm_init_reg_seq[] = { {TOK_TERM, 0, 0}, }; -/** +/* * I2C Device Table - * * name - Name of the actual device/chip. diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 2ace0410d277..f7c6d64e6031 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -214,12 +214,20 @@ void media_gobj_destroy(struct media_gobj *gobj) gobj->mdev = NULL; } +/* + * TODO: Get rid of this. + */ +#define MEDIA_ENTITY_MAX_PADS 512 + int media_entity_pads_init(struct media_entity *entity, u16 num_pads, struct media_pad *pads) { struct media_device *mdev = entity->graph_obj.mdev; unsigned int i; + if (num_pads >= MEDIA_ENTITY_MAX_PADS) + return -E2BIG; + entity->num_pads = num_pads; entity->pads = pads; @@ -280,11 +288,6 @@ static struct media_entity *stack_pop(struct media_graph *graph) #define link_top(en) ((en)->stack[(en)->top].link) #define stack_top(en) ((en)->stack[(en)->top].entity) -/* - * TODO: Get rid of this. - */ -#define MEDIA_ENTITY_MAX_PADS 512 - /** * media_graph_walk_init - Allocate resources for graph walk * @graph: Media graph structure that will be used to walk the graph diff --git a/drivers/media/pci/b2c2/Kconfig b/drivers/media/pci/b2c2/Kconfig index 58761a21caa0..7b818d445f39 100644 --- a/drivers/media/pci/b2c2/Kconfig +++ b/drivers/media/pci/b2c2/Kconfig @@ -11,5 +11,5 @@ config DVB_B2C2_FLEXCOP_PCI_DEBUG depends on DVB_B2C2_FLEXCOP_PCI select DVB_B2C2_FLEXCOP_DEBUG help - Say Y if you want to enable the module option to control debug messages - of all B2C2 FlexCop drivers. + Say Y if you want to enable the module option to control debug messages + of all B2C2 FlexCop drivers. diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 227086a2e99c..b366a7e1d976 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -3652,9 +3652,9 @@ bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup, wake_up(&wakeup->vb.done); } -static void bttv_irq_timeout(unsigned long data) +static void bttv_irq_timeout(struct timer_list *t) { - struct bttv *btv = (struct bttv *)data; + struct bttv *btv = from_timer(btv, t, timeout); struct bttv_buffer_set old,new; struct bttv_buffer *ovbi; struct bttv_buffer *item; @@ -4043,7 +4043,7 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) INIT_LIST_HEAD(&btv->capture); INIT_LIST_HEAD(&btv->vcapture); - setup_timer(&btv->timeout, bttv_irq_timeout, (unsigned long)btv); + timer_setup(&btv->timeout, bttv_irq_timeout, 0); btv->i2c_rc = -1; btv->tuner_type = UNSET; diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c index 73d655d073d6..ac7674700685 100644 --- a/drivers/media/pci/bt8xx/bttv-input.c +++ b/drivers/media/pci/bt8xx/bttv-input.c @@ -133,10 +133,10 @@ void bttv_input_irq(struct bttv *btv) ir_handle_key(btv); } -static void bttv_input_timer(unsigned long data) +static void bttv_input_timer(struct timer_list *t) { - struct bttv *btv = (struct bttv*)data; - struct bttv_ir *ir = btv->remote; + struct bttv_ir *ir = from_timer(ir, t, timer); + struct bttv *btv = ir->btv; if (btv->c.type == BTTV_BOARD_ENLTV_FM_2) ir_enltv_handle_key(btv); @@ -189,9 +189,9 @@ static u32 bttv_rc5_decode(unsigned int code) return rc5; } -static void bttv_rc5_timer_end(unsigned long data) +static void bttv_rc5_timer_end(struct timer_list *t) { - struct bttv_ir *ir = (struct bttv_ir *)data; + struct bttv_ir *ir = from_timer(ir, t, timer); ktime_t tv; u32 gap, rc5, scancode; u8 toggle, command, system; @@ -296,15 +296,15 @@ static int bttv_rc5_irq(struct bttv *btv) /* ---------------------------------------------------------------------- */ -static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir) +static void bttv_ir_start(struct bttv_ir *ir) { if (ir->polling) { - setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv); + timer_setup(&ir->timer, bttv_input_timer, 0); ir->timer.expires = jiffies + msecs_to_jiffies(1000); add_timer(&ir->timer); } else if (ir->rc5_gpio) { /* set timer_end for code completion */ - setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir); + timer_setup(&ir->timer, bttv_rc5_timer_end, 0); ir->shift_by = 1; ir->rc5_remote_gap = ir_rc5_remote_gap; } @@ -531,6 +531,7 @@ int bttv_input_init(struct bttv *btv) /* init input device */ ir->dev = rc; + ir->btv = btv; snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", btv->c.type); @@ -553,7 +554,7 @@ int bttv_input_init(struct bttv *btv) rc->driver_name = MODULE_NAME; btv->remote = ir; - bttv_ir_start(btv, ir); + bttv_ir_start(ir); /* all done */ err = rc_register_device(rc); diff --git a/drivers/media/pci/bt8xx/bttv-vbi.c b/drivers/media/pci/bt8xx/bttv-vbi.c index e77129c92fa0..67c6583f1d79 100644 --- a/drivers/media/pci/bt8xx/bttv-vbi.c +++ b/drivers/media/pci/bt8xx/bttv-vbi.c @@ -233,7 +233,7 @@ static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer bttv_dma_free(q,fh->btv,buf); } -struct videobuf_queue_ops bttv_vbi_qops = { +const struct videobuf_queue_ops bttv_vbi_qops = { .buf_setup = vbi_buffer_setup, .buf_prepare = vbi_buffer_prepare, .buf_queue = vbi_buffer_queue, diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h index 9efc4559fa8e..cb1b5e611130 100644 --- a/drivers/media/pci/bt8xx/bttvp.h +++ b/drivers/media/pci/bt8xx/bttvp.h @@ -122,6 +122,7 @@ struct bttv_format { struct bttv_ir { struct rc_dev *dev; + struct bttv *btv; struct timer_list timer; char name[32]; @@ -281,7 +282,7 @@ int bttv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f); int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f); int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f); -extern struct videobuf_queue_ops bttv_vbi_qops; +extern const struct videobuf_queue_ops bttv_vbi_qops; /* ---------------------------------------------------------- */ /* bttv-gpio.c */ diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c index 98b6cb9505d1..3f16cf3f6d74 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.c +++ b/drivers/media/pci/cobalt/cobalt-driver.c @@ -738,9 +738,6 @@ static int cobalt_probe(struct pci_dev *pci_dev, goto err_i2c; } - retval = v4l2_device_register_subdev_nodes(&cobalt->v4l2_dev); - if (retval) - goto err_i2c; retval = cobalt_nodes_register(cobalt); if (retval) { cobalt_err("Error %d registering device nodes\n", retval); @@ -767,8 +764,6 @@ err_pci: err_wq: destroy_workqueue(cobalt->irq_work_queues); err: - if (retval == 0) - retval = -ENODEV; cobalt_err("error %d on initialization\n", retval); v4l2_device_unregister(&cobalt->v4l2_dev); diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index 8654710464cc..8f314ca320c7 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -255,7 +255,7 @@ static void request_module_async(struct work_struct *work) request_module("cx18-alsa"); /* Initialize cx18-alsa for this instance of the cx18 device */ - if (cx18_ext_init != NULL) + if (cx18_ext_init) cx18_ext_init(dev); } @@ -291,11 +291,11 @@ int cx18_msleep_timeout(unsigned int msecs, int intr) /* Release ioremapped memory */ static void cx18_iounmap(struct cx18 *cx) { - if (cx == NULL) + if (!cx) return; /* Release io memory */ - if (cx->enc_mem != NULL) { + if (cx->enc_mem) { CX18_DEBUG_INFO("releasing enc_mem\n"); iounmap(cx->enc_mem); cx->enc_mem = NULL; @@ -649,15 +649,15 @@ static void cx18_process_options(struct cx18 *cx) CX18_INFO("User specified %s card\n", cx->card->name); else if (cx->options.cardtype != 0) CX18_ERR("Unknown user specified type, trying to autodetect card\n"); - if (cx->card == NULL) { + if (!cx->card) { if (cx->pci_dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) { cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); CX18_INFO("Autodetected Hauppauge card\n"); } } - if (cx->card == NULL) { + if (!cx->card) { for (i = 0; (cx->card = cx18_get_card(i)); i++) { - if (cx->card->pci_list == NULL) + if (!cx->card->pci_list) continue; for (j = 0; cx->card->pci_list[j].device; j++) { if (cx->pci_dev->device != @@ -676,7 +676,7 @@ static void cx18_process_options(struct cx18 *cx) } done: - if (cx->card == NULL) { + if (!cx->card) { cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n", cx->pci_dev->vendor, cx->pci_dev->device); @@ -698,7 +698,7 @@ static int cx18_create_in_workq(struct cx18 *cx) snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in", cx->v4l2_dev.name); cx->in_work_queue = alloc_ordered_workqueue("%s", 0, cx->in_workq_name); - if (cx->in_work_queue == NULL) { + if (!cx->in_work_queue) { CX18_ERR("Unable to create incoming mailbox handler thread\n"); return -ENOMEM; } @@ -909,12 +909,10 @@ static int cx18_probe(struct pci_dev *pci_dev, return -ENOMEM; } - cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC); - if (cx == NULL) { - printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n", - i); + cx = kzalloc(sizeof(*cx), GFP_ATOMIC); + if (!cx) return -ENOMEM; - } + cx->pci_dev = pci_dev; cx->instance = i; @@ -1256,7 +1254,7 @@ static void cx18_cancel_out_work_orders(struct cx18 *cx) { int i; for (i = 0; i < CX18_MAX_STREAMS; i++) - if (&cx->streams[i].video_dev != NULL) + if (&cx->streams[i].video_dev) cancel_work_sync(&cx->streams[i].out_work_order); } @@ -1301,7 +1299,7 @@ static void cx18_remove(struct pci_dev *pci_dev) pci_disable_device(cx->pci_dev); - if (cx->vbi.sliced_mpeg_data[0] != NULL) + if (cx->vbi.sliced_mpeg_data[0]) for (i = 0; i < CX18_VBI_FRAMES; i++) kfree(cx->vbi.sliced_mpeg_data[i]); diff --git a/drivers/media/pci/cx18/cx18-fileops.c b/drivers/media/pci/cx18/cx18-fileops.c index 98467b2089fa..4f9c2395941b 100644 --- a/drivers/media/pci/cx18/cx18-fileops.c +++ b/drivers/media/pci/cx18/cx18-fileops.c @@ -684,9 +684,9 @@ int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma) return -EINVAL; } -void cx18_vb_timeout(unsigned long data) +void cx18_vb_timeout(struct timer_list *t) { - struct cx18_stream *s = (struct cx18_stream *)data; + struct cx18_stream *s = from_timer(s, t, vb_timeout); struct cx18_videobuf_buffer *buf; unsigned long flags; diff --git a/drivers/media/pci/cx18/cx18-fileops.h b/drivers/media/pci/cx18/cx18-fileops.h index 58b00b433708..37ef34e866cb 100644 --- a/drivers/media/pci/cx18/cx18-fileops.h +++ b/drivers/media/pci/cx18/cx18-fileops.h @@ -29,7 +29,7 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end); void cx18_mute(struct cx18 *cx); void cx18_unmute(struct cx18 *cx); int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma); -void cx18_vb_timeout(unsigned long data); +void cx18_vb_timeout(struct timer_list *t); /* Shared with cx18-alsa module */ int cx18_claim_stream(struct cx18_open_id *id, int type); diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c index 8385411af641..f35f78d66985 100644 --- a/drivers/media/pci/cx18/cx18-streams.c +++ b/drivers/media/pci/cx18/cx18-streams.c @@ -282,7 +282,7 @@ static void cx18_stream_init(struct cx18 *cx, int type) INIT_WORK(&s->out_work_order, cx18_out_work_handler); INIT_LIST_HEAD(&s->vb_capture); - setup_timer(&s->vb_timeout, cx18_vb_timeout, (unsigned long)s); + timer_setup(&s->vb_timeout, cx18_vb_timeout, 0); spin_lock_init(&s->vb_lock); if (type == CX18_ENC_STREAM_TYPE_YUV) { spin_lock_init(&s->vbuf_q_lock); diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 78a8836d03e4..28eab9c518c5 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -1323,7 +1323,7 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) static void tbs_card_init(struct cx23885_dev *dev) { int i; - const u8 buf[] = { + static const u8 buf[] = { 0xe0, 0x06, 0x66, 0x33, 0x65, 0x01, 0x17, 0x06, 0xde}; diff --git a/drivers/media/pci/cx23885/cx23885-i2c.c b/drivers/media/pci/cx23885/cx23885-i2c.c index 0f21467ae88e..ef863492c0ac 100644 --- a/drivers/media/pci/cx23885/cx23885-i2c.c +++ b/drivers/media/pci/cx23885/cx23885-i2c.c @@ -270,7 +270,7 @@ static const struct i2c_adapter cx23885_i2c_adap_template = { .algo = &cx23885_i2c_algo_template, }; -static struct i2c_client cx23885_i2c_client_template = { +static const struct i2c_client cx23885_i2c_client_template = { .name = "cx23885 internal", }; diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c index 369e545cac04..70f9f13bded3 100644 --- a/drivers/media/pci/cx23885/cx23885-vbi.c +++ b/drivers/media/pci/cx23885/cx23885-vbi.c @@ -254,7 +254,7 @@ static void cx23885_stop_streaming(struct vb2_queue *q) } -struct vb2_ops cx23885_vbi_qops = { +const struct vb2_ops cx23885_vbi_qops = { .queue_setup = queue_setup, .buf_prepare = buffer_prepare, .buf_finish = buffer_finish, diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h index cb714ab60d69..6aab713e0476 100644 --- a/drivers/media/pci/cx23885/cx23885.h +++ b/drivers/media/pci/cx23885/cx23885.h @@ -591,7 +591,7 @@ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm); extern int cx23885_vbi_fmt(struct file *file, void *priv, struct v4l2_format *f); extern void cx23885_vbi_timeout(unsigned long data); -extern struct vb2_ops cx23885_vbi_qops; +extern const struct vb2_ops cx23885_vbi_qops; extern int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status); /* cx23885-i2c.c */ diff --git a/drivers/media/pci/cx25821/cx25821-i2c.c b/drivers/media/pci/cx25821/cx25821-i2c.c index 000049d3c71b..31479a41f359 100644 --- a/drivers/media/pci/cx25821/cx25821-i2c.c +++ b/drivers/media/pci/cx25821/cx25821-i2c.c @@ -291,7 +291,7 @@ static const struct i2c_adapter cx25821_i2c_adap_template = { .algo = &cx25821_i2c_algo_template, }; -static struct i2c_client cx25821_i2c_client_template = { +static const struct i2c_client cx25821_i2c_client_template = { .name = "cx25821 internal", }; diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c index e02449bf2041..4e9953e61a12 100644 --- a/drivers/media/pci/cx88/cx88-input.c +++ b/drivers/media/pci/cx88/cx88-input.c @@ -593,11 +593,11 @@ static int get_key_pvr2000(struct IR_i2c *ir, enum rc_proto *protocol, void cx88_i2c_init_ir(struct cx88_core *core) { struct i2c_board_info info; - const unsigned short default_addr_list[] = { + static const unsigned short default_addr_list[] = { 0x18, 0x6b, 0x71, I2C_CLIENT_END }; - const unsigned short pvr2000_addr_list[] = { + static const unsigned short pvr2000_addr_list[] = { 0x18, 0x1a, I2C_CLIENT_END }; diff --git a/drivers/media/pci/ddbridge/ddbridge-io.h b/drivers/media/pci/ddbridge/ddbridge-io.h index a4c6bbe09168..b3646c04f1a7 100644 --- a/drivers/media/pci/ddbridge/ddbridge-io.h +++ b/drivers/media/pci/ddbridge/ddbridge-io.h @@ -47,12 +47,12 @@ static inline void ddbwritel(struct ddb *dev, u32 val, u32 adr) static inline void ddbcpyto(struct ddb *dev, u32 adr, void *src, long count) { - return memcpy_toio(dev->regs + adr, src, count); + memcpy_toio(dev->regs + adr, src, count); } static inline void ddbcpyfrom(struct ddb *dev, void *dst, u32 adr, long count) { - return memcpy_fromio(dst, dev->regs + adr, count); + memcpy_fromio(dst, dev->regs + adr, count); } static inline u32 safe_ddbreadl(struct ddb *dev, u32 adr) diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index 54dcac4b2229..6b2ffdc96961 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -770,8 +770,7 @@ static int ivtv_init_struct1(struct ivtv *itv) init_waitqueue_head(&itv->event_waitq); init_waitqueue_head(&itv->vsync_waitq); init_waitqueue_head(&itv->dma_waitq); - setup_timer(&itv->dma_timer, ivtv_unfinished_dma, - (unsigned long)itv); + timer_setup(&itv->dma_timer, ivtv_unfinished_dma, 0); itv->cur_dma_stream = -1; itv->cur_pio_stream = -1; diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c index 5a35e366f4c0..893962ac85de 100644 --- a/drivers/media/pci/ivtv/ivtv-i2c.c +++ b/drivers/media/pci/ivtv/ivtv-i2c.c @@ -700,7 +700,7 @@ static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { .timeout = IVTV_ALGO_BIT_TIMEOUT * HZ, /* jiffies */ }; -static struct i2c_client ivtv_i2c_client_template = { +static const struct i2c_client ivtv_i2c_client_template = { .name = "ivtv internal", }; diff --git a/drivers/media/pci/ivtv/ivtv-irq.c b/drivers/media/pci/ivtv/ivtv-irq.c index 6efe1f71262c..63b09bf73bf0 100644 --- a/drivers/media/pci/ivtv/ivtv-irq.c +++ b/drivers/media/pci/ivtv/ivtv-irq.c @@ -1074,9 +1074,9 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) return vsync_force ? IRQ_NONE : IRQ_HANDLED; } -void ivtv_unfinished_dma(unsigned long arg) +void ivtv_unfinished_dma(struct timer_list *t) { - struct ivtv *itv = (struct ivtv *)arg; + struct ivtv *itv = from_timer(itv, t, dma_timer); if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) return; diff --git a/drivers/media/pci/ivtv/ivtv-irq.h b/drivers/media/pci/ivtv/ivtv-irq.h index 1e84433737cc..bcab5f07d37f 100644 --- a/drivers/media/pci/ivtv/ivtv-irq.h +++ b/drivers/media/pci/ivtv/ivtv-irq.h @@ -48,6 +48,6 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id); void ivtv_irq_work_handler(struct kthread_work *work); void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock); -void ivtv_unfinished_dma(unsigned long arg); +void ivtv_unfinished_dma(struct timer_list *t); #endif diff --git a/drivers/media/pci/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c index 11e987860b23..ed855e3df558 100644 --- a/drivers/media/pci/mantis/hopper_cards.c +++ b/drivers/media/pci/mantis/hopper_cards.c @@ -72,7 +72,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id) struct mantis_ca *ca; mantis = (struct mantis_pci *) dev_id; - if (unlikely(mantis == NULL)) { + if (unlikely(!mantis)) { dprintk(MANTIS_ERROR, 1, "Mantis == NULL"); return IRQ_NONE; } @@ -161,11 +161,10 @@ static int hopper_pci_probe(struct pci_dev *pdev, struct mantis_pci_drvdata *drvdata; struct mantis_pci *mantis; struct mantis_hwconfig *config; - int err = 0; + int err; - mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL); - if (mantis == NULL) { - printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); + mantis = kzalloc(sizeof(*mantis), GFP_KERNEL); + if (!mantis) { err = -ENOMEM; goto fail0; } diff --git a/drivers/media/pci/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c index adc980d33711..4ce8a90d69dc 100644 --- a/drivers/media/pci/mantis/mantis_cards.c +++ b/drivers/media/pci/mantis/mantis_cards.c @@ -171,13 +171,11 @@ static int mantis_pci_probe(struct pci_dev *pdev, struct mantis_pci_drvdata *drvdata; struct mantis_pci *mantis; struct mantis_hwconfig *config; - int err = 0; + int err; - mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL); - if (mantis == NULL) { - printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); + mantis = kzalloc(sizeof(*mantis), GFP_KERNEL); + if (!mantis) return -ENOMEM; - } drvdata = (void *)pci_id->driver_data; mantis->num = devs; diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c index 49e047e4a81e..23999a8cef37 100644 --- a/drivers/media/pci/meye/meye.c +++ b/drivers/media/pci/meye/meye.c @@ -1626,35 +1626,31 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) meye.mchip_dev = pcidev; meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); - if (!meye.grab_temp) { - v4l2_err(v4l2_dev, "grab buffer allocation failed\n"); + if (!meye.grab_temp) goto outvmalloc; - } spin_lock_init(&meye.grabq_lock); if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, - GFP_KERNEL)) { - v4l2_err(v4l2_dev, "fifo allocation failed\n"); + GFP_KERNEL)) goto outkfifoalloc1; - } + spin_lock_init(&meye.doneq_lock); if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, - GFP_KERNEL)) { - v4l2_err(v4l2_dev, "fifo allocation failed\n"); + GFP_KERNEL)) goto outkfifoalloc2; - } meye.vdev = meye_template; meye.vdev.v4l2_dev = &meye.v4l2_dev; - ret = -EIO; - if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) { + ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1); + if (ret) { v4l2_err(v4l2_dev, "meye: unable to power on the camera\n"); v4l2_err(v4l2_dev, "meye: did you enable the camera in sonypi using the module options ?\n"); goto outsonypienable; } - if ((ret = pci_enable_device(meye.mchip_dev))) { + ret = pci_enable_device(meye.mchip_dev); + if (ret) { v4l2_err(v4l2_dev, "meye: pci_enable_device failed\n"); goto outenabledev; } diff --git a/drivers/media/pci/netup_unidvb/Kconfig b/drivers/media/pci/netup_unidvb/Kconfig index 0ad37714c7fd..b663154d0cc4 100644 --- a/drivers/media/pci/netup_unidvb/Kconfig +++ b/drivers/media/pci/netup_unidvb/Kconfig @@ -1,8 +1,8 @@ config DVB_NETUP_UNIDVB tristate "NetUP Universal DVB card support" depends on DVB_CORE && VIDEO_DEV && PCI && I2C && SPI_MASTER - select VIDEOBUF2_DVB - select VIDEOBUF2_VMALLOC + select VIDEOBUF2_DVB + select VIDEOBUF2_VMALLOC select DVB_HORUS3A if MEDIA_SUBDRV_AUTOSELECT select DVB_ASCOT2E if MEDIA_SUBDRV_AUTOSELECT select DVB_HELENE if MEDIA_SUBDRV_AUTOSELECT @@ -10,8 +10,8 @@ config DVB_NETUP_UNIDVB select DVB_CXD2841ER if MEDIA_SUBDRV_AUTOSELECT ---help--- Support for NetUP PCI express Universal DVB card. - help - Say Y when you want to support NetUP Dual Universal DVB card - Card can receive two independent streams in following standards: + + Say Y when you want to support NetUP Dual Universal DVB card. + Card can receive two independent streams in following standards: DVB-S/S2, T/T2, C/C2 - Two CI slots available for CAM modules. + Two CI slots available for CAM modules. diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 60e6cd5b3a03..509d69e6ca4a 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -82,11 +82,11 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); * @start_addr_lo: DMA ring buffer start address, lower part * @start_addr_hi: DMA ring buffer start address, higher part * @size: DMA ring buffer size register - Bits [0-7]: DMA packet size, 188 bytes - Bits [16-23]: packets count in block, 128 packets - Bits [24-31]: blocks count, 8 blocks + * * Bits [0-7]: DMA packet size, 188 bytes + * * Bits [16-23]: packets count in block, 128 packets + * * Bits [24-31]: blocks count, 8 blocks * @timeout: DMA timeout in units of 8ns - For example, value of 375000000 equals to 3 sec + * For example, value of 375000000 equals to 3 sec * @curr_addr_lo: Current ring buffer head address, lower part * @curr_addr_hi: Current ring buffer head address, higher part * @stat_pkt_received: Statistic register, not tested @@ -638,9 +638,9 @@ static void netup_unidvb_queue_cleanup(struct netup_dma *dma) spin_unlock_irqrestore(&dma->lock, flags); } -static void netup_unidvb_dma_timeout(unsigned long data) +static void netup_unidvb_dma_timeout(struct timer_list *t) { - struct netup_dma *dma = (struct netup_dma *)data; + struct netup_dma *dma = from_timer(dma, t, timeout); struct netup_unidvb_dev *ndev = dma->ndev; dev_dbg(&ndev->pci_dev->dev, "%s()\n", __func__); @@ -664,8 +664,7 @@ static int netup_unidvb_dma_init(struct netup_unidvb_dev *ndev, int num) spin_lock_init(&dma->lock); INIT_WORK(&dma->work, netup_unidvb_dma_worker); INIT_LIST_HEAD(&dma->free_buffers); - setup_timer(&dma->timeout, netup_unidvb_dma_timeout, - (unsigned long)dma); + timer_setup(&dma->timeout, netup_unidvb_dma_timeout, 0); dma->ring_buffer_size = ndev->dma_size / 2; dma->addr_virt = ndev->dma_virt + dma->ring_buffer_size * num; dma->addr_phys = (dma_addr_t)((u64)ndev->dma_phys + diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index 7976c5a12ca8..9e76de2411ae 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -338,9 +338,9 @@ void saa7134_buffer_next(struct saa7134_dev *dev, } } -void saa7134_buffer_timeout(unsigned long data) +void saa7134_buffer_timeout(struct timer_list *t) { - struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue *)data; + struct saa7134_dmaqueue *q = from_timer(q, t, timeout); struct saa7134_dev *dev = q->dev; unsigned long flags; @@ -378,7 +378,7 @@ void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q) } } spin_unlock_irqrestore(&dev->slock, flags); - saa7134_buffer_timeout((unsigned long)q); /* also calls del_timer(&q->timeout) */ + saa7134_buffer_timeout(&q->timeout); /* also calls del_timer(&q->timeout) */ } EXPORT_SYMBOL_GPL(saa7134_stop_streaming); diff --git a/drivers/media/pci/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c index 8f2ed632840f..cf1e526de56a 100644 --- a/drivers/media/pci/saa7134/saa7134-i2c.c +++ b/drivers/media/pci/saa7134/saa7134-i2c.c @@ -345,7 +345,7 @@ static const struct i2c_adapter saa7134_adap_template = { .algo = &saa7134_algo, }; -static struct i2c_client saa7134_client_template = { +static const struct i2c_client saa7134_client_template = { .name = "saa7134 internal", }; diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c index 9337e4615519..2d5abeddc079 100644 --- a/drivers/media/pci/saa7134/saa7134-input.c +++ b/drivers/media/pci/saa7134/saa7134-input.c @@ -447,10 +447,10 @@ void saa7134_input_irq(struct saa7134_dev *dev) } } -static void saa7134_input_timer(unsigned long data) +static void saa7134_input_timer(struct timer_list *t) { - struct saa7134_dev *dev = (struct saa7134_dev *)data; - struct saa7134_card_ir *ir = dev->remote; + struct saa7134_card_ir *ir = from_timer(ir, t, timer); + struct saa7134_dev *dev = ir->dev->priv; build_key(dev); mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); @@ -507,8 +507,7 @@ static int __saa7134_ir_start(void *priv) ir->running = true; if (ir->polling) { - setup_timer(&ir->timer, saa7134_input_timer, - (unsigned long)dev); + timer_setup(&ir->timer, saa7134_input_timer, 0); ir->timer.expires = jiffies + HZ; add_timer(&ir->timer); } diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c index 7414878af9e0..2be703617e29 100644 --- a/drivers/media/pci/saa7134/saa7134-ts.c +++ b/drivers/media/pci/saa7134/saa7134-ts.c @@ -223,8 +223,7 @@ int saa7134_ts_init1(struct saa7134_dev *dev) dev->ts.nr_packets = ts_nr_packets; INIT_LIST_HEAD(&dev->ts_q.queue); - setup_timer(&dev->ts_q.timeout, saa7134_buffer_timeout, - (unsigned long)(&dev->ts_q)); + timer_setup(&dev->ts_q.timeout, saa7134_buffer_timeout, 0); dev->ts_q.dev = dev; dev->ts_q.need_two = 1; dev->ts_started = 0; diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c index bcad9b2d9bb3..57bea543c39b 100644 --- a/drivers/media/pci/saa7134/saa7134-vbi.c +++ b/drivers/media/pci/saa7134/saa7134-vbi.c @@ -165,7 +165,7 @@ static int buffer_init(struct vb2_buffer *vb2) return 0; } -struct vb2_ops saa7134_vbi_qops = { +const struct vb2_ops saa7134_vbi_qops = { .queue_setup = queue_setup, .buf_init = buffer_init, .buf_prepare = buffer_prepare, @@ -181,8 +181,7 @@ struct vb2_ops saa7134_vbi_qops = { int saa7134_vbi_init1(struct saa7134_dev *dev) { INIT_LIST_HEAD(&dev->vbi_q.queue); - setup_timer(&dev->vbi_q.timeout, saa7134_buffer_timeout, - (unsigned long)(&dev->vbi_q)); + timer_setup(&dev->vbi_q.timeout, saa7134_buffer_timeout, 0); dev->vbi_q.dev = dev; if (vbibufs < 2) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 51d42bbf969e..82d2a24644e4 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -2145,8 +2145,7 @@ int saa7134_video_init1(struct saa7134_dev *dev) dev->automute = 0; INIT_LIST_HEAD(&dev->video_q.queue); - setup_timer(&dev->video_q.timeout, saa7134_buffer_timeout, - (unsigned long)(&dev->video_q)); + timer_setup(&dev->video_q.timeout, saa7134_buffer_timeout, 0); dev->video_q.dev = dev; dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); dev->width = 720; diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 816b5282d671..39c36e6aefbe 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -773,7 +773,7 @@ int saa7134_buffer_queue(struct saa7134_dev *dev, struct saa7134_dmaqueue *q, void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q, unsigned int state); void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q); -void saa7134_buffer_timeout(unsigned long data); +void saa7134_buffer_timeout(struct timer_list *t); void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q); int saa7134_set_dmabits(struct saa7134_dev *dev); @@ -870,7 +870,7 @@ int saa7134_ts_stop(struct saa7134_dev *dev); /* ----------------------------------------------------------- */ /* saa7134-vbi.c */ -extern struct vb2_ops saa7134_vbi_qops; +extern const struct vb2_ops saa7134_vbi_qops; extern struct video_device saa7134_vbi_template; int saa7134_vbi_init1(struct saa7134_dev *dev); diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c index f708cab01fef..d31a2d4494d1 100644 --- a/drivers/media/pci/saa7146/hexium_gemini.c +++ b/drivers/media/pci/saa7146/hexium_gemini.c @@ -260,11 +260,10 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d DEB_EE("\n"); - hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); - if (NULL == hexium) { - pr_err("not enough kernel memory in hexium_attach()\n"); + hexium = kzalloc(sizeof(*hexium), GFP_KERNEL); + if (!hexium) return -ENOMEM; - } + dev->ext_priv = hexium; /* enable i2c-port pins */ diff --git a/drivers/media/pci/saa7146/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c index 01f01580c7ca..043318aa19e2 100644 --- a/drivers/media/pci/saa7146/hexium_orion.c +++ b/drivers/media/pci/saa7146/hexium_orion.c @@ -219,11 +219,9 @@ static int hexium_probe(struct saa7146_dev *dev) return -EFAULT; } - hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); - if (NULL == hexium) { - pr_err("hexium_probe: not enough kernel memory\n"); + hexium = kzalloc(sizeof(*hexium), GFP_KERNEL); + if (!hexium) return -ENOMEM; - } /* enable i2c-port pins */ saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); @@ -268,7 +266,9 @@ static int hexium_probe(struct saa7146_dev *dev) /* check if this is an old hexium Orion card by looking at a saa7110 at address 0x4e */ - if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) { + err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, + 0x00, I2C_SMBUS_BYTE_DATA, &data); + if (err == 0) { pr_info("device is a Hexium HV-PCI6/Orion (old)\n"); /* we store the pointer in our private data field */ dev->ext_priv = hexium; diff --git a/drivers/media/pci/saa7164/saa7164-buffer.c b/drivers/media/pci/saa7164/saa7164-buffer.c index a0d2129c6ca9..c83b2e914dcb 100644 --- a/drivers/media/pci/saa7164/saa7164-buffer.c +++ b/drivers/media/pci/saa7164/saa7164-buffer.c @@ -98,11 +98,9 @@ struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port, goto ret; } - buf = kzalloc(sizeof(struct saa7164_buffer), GFP_KERNEL); - if (!buf) { - log_warn("%s() SAA_ERR_NO_RESOURCES\n", __func__); + buf = kzalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) goto ret; - } buf->idx = -1; buf->port = port; @@ -283,7 +281,7 @@ struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev, { struct saa7164_user_buffer *buf; - buf = kzalloc(sizeof(struct saa7164_user_buffer), GFP_KERNEL); + buf = kzalloc(sizeof(*buf), GFP_KERNEL); if (!buf) return NULL; diff --git a/drivers/media/pci/saa7164/saa7164-i2c.c b/drivers/media/pci/saa7164/saa7164-i2c.c index 4bcde7c79dc3..6d13cbb9d010 100644 --- a/drivers/media/pci/saa7164/saa7164-i2c.c +++ b/drivers/media/pci/saa7164/saa7164-i2c.c @@ -84,7 +84,7 @@ static const struct i2c_adapter saa7164_i2c_adap_template = { .algo = &saa7164_i2c_algo_template, }; -static struct i2c_client saa7164_i2c_client_template = { +static const struct i2c_client saa7164_i2c_client_template = { .name = "saa7164 internal", }; diff --git a/drivers/media/pci/solo6x10/solo6x10-enc.c b/drivers/media/pci/solo6x10/solo6x10-enc.c index d28211bb9674..58d6b5131dd0 100644 --- a/drivers/media/pci/solo6x10/solo6x10-enc.c +++ b/drivers/media/pci/solo6x10/solo6x10-enc.c @@ -175,7 +175,7 @@ out: return 0; } -/** +/* * Set channel Quality Profile (0-3). */ void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch, diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index eb5a9eae7c8e..dd199bfc1d45 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -404,6 +404,7 @@ static const struct v4l2_file_operations vip_fops = { * vidioc_querycap - return capabilities of device * @file: descriptor of device * @cap: contains return values + * @priv: unused * * the capabilities of the device are returned * @@ -429,6 +430,7 @@ static int vidioc_querycap(struct file *file, void *priv, * vidioc_s_std - set video standard * @file: descriptor of device * @std: contains standard to be set + * @priv: unused * * the video standard is set * @@ -466,6 +468,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) /** * vidioc_g_std - get video standard * @file: descriptor of device + * @priv: unused * @std: contains return values * * the current video standard is returned @@ -483,6 +486,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std) /** * vidioc_querystd - get possible video standards * @file: descriptor of device + * @priv: unused * @std: contains return values * * all possible video standards are returned @@ -512,6 +516,7 @@ static int vidioc_enum_input(struct file *file, void *priv, /** * vidioc_s_input - set input line * @file: descriptor of device + * @priv: unused * @i: new input line number * * the current active input line is set @@ -538,6 +543,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) /** * vidioc_g_input - return input line * @file: descriptor of device + * @priv: unused * @i: returned input line number * * the current active input line is returned @@ -554,6 +560,8 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) /** * vidioc_enum_fmt_vid_cap - return video capture format + * @file: descriptor of device + * @priv: unused * @f: returned format information * * returns name and format of video capture @@ -577,6 +585,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, /** * vidioc_try_fmt_vid_cap - set video capture format * @file: descriptor of device + * @priv: unused * @f: new format * * new video format is set which includes width and @@ -639,6 +648,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, /** * vidioc_s_fmt_vid_cap - set current video format parameters * @file: descriptor of device + * @priv: unused * @f: returned format information * * set new capture format @@ -706,6 +716,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, /** * vidioc_g_fmt_vid_cap - get current video format parameters * @file: descriptor of device + * @priv: unused * @f: contains format information * * returns current video format parameters diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index f46947d8adf8..6d415bdeef18 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -347,9 +347,9 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len, static inline void print_time(char *s) { #ifdef DEBUG_TIMING - struct timeval tv; - do_gettimeofday(&tv); - printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec); + struct timespec64 ts; + ktime_get_real_ts64(&ts); + printk("%s: %lld.%09ld\n", s, (s64)ts.tv_sec, ts.tv_nsec); #endif } @@ -1224,7 +1224,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed) dprintk(2, "av7110: %p\n", budget); spin_lock(&budget->feedlock1); - feed->pusi_seen = 0; /* have a clean section start */ + feed->pusi_seen = false; /* have a clean section start */ status = start_ts_capture(budget); spin_unlock(&budget->feedlock1); return status; diff --git a/drivers/media/pci/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h index cd09fd6e6548..cbb150d6cbb1 100644 --- a/drivers/media/pci/ttpci/av7110.h +++ b/drivers/media/pci/ttpci/av7110.h @@ -94,7 +94,7 @@ struct infrared { u8 inversion; u16 last_key; u16 last_toggle; - u8 delay_timer_finished; + bool keypressed; }; diff --git a/drivers/media/pci/ttpci/av7110_ir.c b/drivers/media/pci/ttpci/av7110_ir.c index ca05198de2c2..ee414803e6b5 100644 --- a/drivers/media/pci/ttpci/av7110_ir.c +++ b/drivers/media/pci/ttpci/av7110_ir.c @@ -84,15 +84,16 @@ static u16 default_key_map [256] = { /* key-up timer */ -static void av7110_emit_keyup(unsigned long parm) +static void av7110_emit_keyup(struct timer_list *t) { - struct infrared *ir = (struct infrared *) parm; + struct infrared *ir = from_timer(ir, t, keyup_timer); - if (!ir || !test_bit(ir->last_key, ir->input_dev->key)) + if (!ir || !ir->keypressed) return; input_report_key(ir->input_dev, ir->last_key, 0); input_sync(ir->input_dev); + ir->keypressed = false; } @@ -152,29 +153,18 @@ static void av7110_emit_key(unsigned long parm) return; } - if (timer_pending(&ir->keyup_timer)) { - del_timer(&ir->keyup_timer); - if (ir->last_key != keycode || toggle != ir->last_toggle) { - ir->delay_timer_finished = 0; - input_event(ir->input_dev, EV_KEY, ir->last_key, 0); - input_event(ir->input_dev, EV_KEY, keycode, 1); - input_sync(ir->input_dev); - } else if (ir->delay_timer_finished) { - input_event(ir->input_dev, EV_KEY, keycode, 2); - input_sync(ir->input_dev); - } - } else { - ir->delay_timer_finished = 0; - input_event(ir->input_dev, EV_KEY, keycode, 1); - input_sync(ir->input_dev); - } + if (ir->keypressed && + (ir->last_key != keycode || toggle != ir->last_toggle)) + input_event(ir->input_dev, EV_KEY, ir->last_key, 0); + input_event(ir->input_dev, EV_KEY, keycode, 1); + input_sync(ir->input_dev); + + ir->keypressed = true; ir->last_key = keycode; ir->last_toggle = toggle; - ir->keyup_timer.expires = jiffies + UP_TIMEOUT; - add_timer(&ir->keyup_timer); - + mod_timer(&ir->keyup_timer, jiffies + UP_TIMEOUT); } @@ -204,16 +194,6 @@ static void input_register_keys(struct infrared *ir) ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); } - -/* called by the input driver after rep[REP_DELAY] ms */ -static void input_repeat_key(unsigned long parm) -{ - struct infrared *ir = (struct infrared *) parm; - - ir->delay_timer_finished = 1; -} - - /* check for configuration changes */ int av7110_check_ir_config(struct av7110 *av7110, int force) { @@ -333,8 +313,7 @@ int av7110_ir_init(struct av7110 *av7110) av_list[av_cnt++] = av7110; av7110_check_ir_config(av7110, true); - setup_timer(&av7110->ir.keyup_timer, av7110_emit_keyup, - (unsigned long)&av7110->ir); + timer_setup(&av7110->ir.keyup_timer, av7110_emit_keyup, 0); input_dev = input_allocate_device(); if (!input_dev) @@ -365,8 +344,13 @@ int av7110_ir_init(struct av7110 *av7110) input_free_device(input_dev); return err; } - input_dev->timer.function = input_repeat_key; - input_dev->timer.data = (unsigned long) &av7110->ir; + + /* + * Input core's default autorepeat is 33 cps with 250 msec + * delay, let's adjust to numbers more suitable for remote + * control. + */ + input_enable_softrepeat(input_dev, 250, 125); if (av_cnt == 1) { e = proc_create("av7110_ir", S_IWUSR, NULL, &av7110_ir_proc_fops); diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c index 97499b2af714..b3dc45b91101 100644 --- a/drivers/media/pci/ttpci/budget-core.c +++ b/drivers/media/pci/ttpci/budget-core.c @@ -330,7 +330,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed) return -EINVAL; spin_lock(&budget->feedlock); - feed->pusi_seen = 0; /* have a clean section start */ + feed->pusi_seen = false; /* have a clean section start */ if (budget->feeding++ == 0) status = start_ts_capture(budget); spin_unlock(&budget->feedlock); diff --git a/drivers/media/pci/tw68/tw68-risc.c b/drivers/media/pci/tw68/tw68-risc.c index 7439db212a69..82ff9c9494f3 100644 --- a/drivers/media/pci/tw68/tw68-risc.c +++ b/drivers/media/pci/tw68/tw68-risc.c @@ -29,14 +29,15 @@ #include "tw68.h" /** - * @rp pointer to current risc program position - * @sglist pointer to "scatter-gather list" of buffer pointers - * @offset offset to target memory buffer - * @sync_line 0 -> no sync, 1 -> odd sync, 2 -> even sync - * @bpl number of bytes per scan line - * @padding number of bytes of padding to add - * @lines number of lines in field - * @jump insert a jump at the start + * tw68_risc_field + * @rp: pointer to current risc program position + * @sglist: pointer to "scatter-gather list" of buffer pointers + * @offset: offset to target memory buffer + * @sync_line: 0 -> no sync, 1 -> odd sync, 2 -> even sync + * @bpl: number of bytes per scan line + * @padding: number of bytes of padding to add + * @lines: number of lines in field + * @jump: insert a jump at the start */ static __le32 *tw68_risc_field(__le32 *rp, struct scatterlist *sglist, unsigned int offset, u32 sync_line, @@ -120,18 +121,18 @@ static __le32 *tw68_risc_field(__le32 *rp, struct scatterlist *sglist, * memory for the dma controller "program" and then fills in that * memory with the appropriate "instructions". * - * @pci_dev structure with info about the pci + * @pci: structure with info about the pci * slot which our device is in. - * @risc structure with info about the memory + * @buf: structure with info about the memory * used for our controller program. - * @sglist scatter-gather list entry - * @top_offset offset within the risc program area for the + * @sglist: scatter-gather list entry + * @top_offset: offset within the risc program area for the * first odd frame line - * @bottom_offset offset within the risc program area for the + * @bottom_offset: offset within the risc program area for the * first even frame line - * @bpl number of data bytes per scan line - * @padding number of extra bytes to add at end of line - * @lines number of scan lines + * @bpl: number of data bytes per scan line + * @padding: number of extra bytes to add at end of line + * @lines: number of scan lines */ int tw68_risc_buffer(struct pci_dev *pci, struct tw68_buf *buf, diff --git a/drivers/media/pci/tw686x/tw686x-core.c b/drivers/media/pci/tw686x/tw686x-core.c index 336e2f9bc1b6..7fb3f07bf022 100644 --- a/drivers/media/pci/tw686x/tw686x-core.c +++ b/drivers/media/pci/tw686x/tw686x-core.c @@ -72,12 +72,12 @@ static const char *dma_mode_name(unsigned int mode) } } -static int tw686x_dma_mode_get(char *buffer, struct kernel_param *kp) +static int tw686x_dma_mode_get(char *buffer, const struct kernel_param *kp) { return sprintf(buffer, "%s", dma_mode_name(dma_mode)); } -static int tw686x_dma_mode_set(const char *val, struct kernel_param *kp) +static int tw686x_dma_mode_set(const char *val, const struct kernel_param *kp) { if (!strcasecmp(val, dma_mode_name(TW686X_DMA_MODE_MEMCPY))) dma_mode = TW686X_DMA_MODE_MEMCPY; @@ -126,9 +126,9 @@ void tw686x_enable_channel(struct tw686x_dev *dev, unsigned int channel) * channels "too fast" which makes some TW686x devices very * angry and freeze the CPU (see note 1). */ -static void tw686x_dma_delay(unsigned long data) +static void tw686x_dma_delay(struct timer_list *t) { - struct tw686x_dev *dev = (struct tw686x_dev *)data; + struct tw686x_dev *dev = from_timer(dev, t, dma_delay_timer); unsigned long flags; spin_lock_irqsave(&dev->lock, flags); @@ -325,8 +325,7 @@ static int tw686x_probe(struct pci_dev *pci_dev, goto iounmap; } - setup_timer(&dev->dma_delay_timer, - tw686x_dma_delay, (unsigned long) dev); + timer_setup(&dev->dma_delay_timer, tw686x_dma_delay, 0); /* * This must be set right before initializing v4l2_dev. diff --git a/drivers/media/pci/zoran/zoran_card.h b/drivers/media/pci/zoran/zoran_card.h index 81cba177cd90..0cdb7d34926d 100644 --- a/drivers/media/pci/zoran/zoran_card.h +++ b/drivers/media/pci/zoran/zoran_card.h @@ -37,7 +37,7 @@ extern int zr36067_debug; /* Anybody who uses more than four? */ #define BUZ_MAX 4 -extern struct video_device zoran_template; +extern const struct video_device zoran_template; extern int zoran_check_jpg_settings(struct zoran *zr, struct zoran_jpg_settings *settings, diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index a11cb501c550..d07840072337 100644 --- a/drivers/media/pci/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -2839,7 +2839,7 @@ static const struct v4l2_file_operations zoran_fops = { .poll = zoran_poll, }; -struct video_device zoran_template = { +const struct video_device zoran_template = { .name = ZORAN_NAME, .fops = &zoran_fops, .ioctl_ops = &zoran_ioctl_ops, diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 3c4f7fa7b9d8..fd0c99859d6f 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -458,6 +458,21 @@ config VIDEO_RENESAS_VSP1 To compile this driver as a module, choose M here: the module will be called vsp1. +config VIDEO_ROCKCHIP_RGA + tristate "Rockchip Raster 2d Graphic Acceleration Unit" + depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA + depends on ARCH_ROCKCHIP || COMPILE_TEST + select VIDEOBUF2_DMA_SG + select V4L2_MEM2MEM_DEV + default n + ---help--- + This is a v4l2 driver for Rockchip SOC RGA 2d graphics accelerator. + Rockchip RGA is a separate 2D raster graphic acceleration unit. + It accelerates 2D graphics operations, such as point/line drawing, + image scaling, rotation, BitBLT, alpha blending and image blur/sharpness. + + To compile this driver as a module choose m here. + config VIDEO_TI_VPE tristate "TI VPE (Video Processing Engine) driver" depends on VIDEO_DEV && VIDEO_V4L2 @@ -553,6 +568,16 @@ config VIDEO_MESON_AO_CEC This is a driver for Amlogic Meson SoCs AO CEC interface. It uses the generic CEC framework interface. CEC bus is present in the HDMI connector and enables communication + +config CEC_GPIO + tristate "Generic GPIO-based CEC driver" + depends on PREEMPT + select CEC_CORE + select CEC_PIN + select GPIOLIB + ---help--- + This is a generic GPIO-based CEC driver. + The CEC bus is present in the HDMI connector and enables communication between compatible devices. config VIDEO_SAMSUNG_S5P_CEC @@ -589,6 +614,17 @@ config VIDEO_STM32_HDMI_CEC CEC bus is present in the HDMI connector and enables communication between compatible devices. +config VIDEO_TEGRA_HDMI_CEC + tristate "Tegra HDMI CEC driver" + depends on ARCH_TEGRA || COMPILE_TEST + select CEC_CORE + select CEC_NOTIFIER + ---help--- + This is a driver for the Tegra HDMI CEC interface. It uses the + generic CEC framework interface. + The CEC bus is present in the HDMI connector and enables communication + between compatible devices. + endif #CEC_PLATFORM_DRIVERS menuconfig SDR_PLATFORM_DRIVERS diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 327f80a6f82c..003b0bb2cddf 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -27,6 +27,8 @@ obj-$(CONFIG_VIDEO_CODA) += coda/ obj-$(CONFIG_VIDEO_SH_VEU) += sh_veu.o +obj-$(CONFIG_CEC_GPIO) += cec-gpio/ + obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE) += m2m-deinterlace.o obj-$(CONFIG_VIDEO_MUX) += video-mux.o @@ -47,6 +49,8 @@ obj-$(CONFIG_VIDEO_STI_HDMI_CEC) += sti/cec/ obj-$(CONFIG_VIDEO_STI_DELTA) += sti/delta/ +obj-$(CONFIG_VIDEO_TEGRA_HDMI_CEC) += tegra-cec/ + obj-y += stm32/ obj-y += blackfin/ @@ -63,6 +67,8 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1) += rcar_fdp1.o obj-$(CONFIG_VIDEO_RENESAS_JPU) += rcar_jpu.o obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/ +obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip/rga/ + obj-y += omap/ obj-$(CONFIG_VIDEO_AM437X_VPFE) += am437x/ diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index dfcc484cab89..0997c640191d 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -2417,6 +2417,11 @@ static int vpfe_async_complete(struct v4l2_async_notifier *notifier) return vpfe_probe_complete(vpfe); } +static const struct v4l2_async_notifier_operations vpfe_async_ops = { + .bound = vpfe_async_bound, + .complete = vpfe_async_complete, +}; + static struct vpfe_config * vpfe_get_pdata(struct platform_device *pdev) { @@ -2590,8 +2595,7 @@ static int vpfe_probe(struct platform_device *pdev) vpfe->notifier.subdevs = vpfe->cfg->asd; vpfe->notifier.num_subdevs = ARRAY_SIZE(vpfe->cfg->asd); - vpfe->notifier.bound = vpfe_async_bound; - vpfe->notifier.complete = vpfe_async_complete; + vpfe->notifier.ops = &vpfe_async_ops; ret = v4l2_async_notifier_register(&vpfe->v4l2_dev, &vpfe->notifier); if (ret) { diff --git a/drivers/media/platform/atmel/atmel-isc-regs.h b/drivers/media/platform/atmel/atmel-isc-regs.h index e6cef966dcbf..2aadc19235ea 100644 --- a/drivers/media/platform/atmel/atmel-isc-regs.h +++ b/drivers/media/platform/atmel/atmel-isc-regs.h @@ -43,6 +43,7 @@ /* ISC Clock Status Register */ #define ISC_CLKSR 0x00000020 +#define ISC_CLKSR_SIP BIT(31) #define ISC_CLK(n) BIT(n) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index d7103c5f92c3..13f1c1c797b0 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -65,6 +65,7 @@ struct isc_clk { struct clk_hw hw; struct clk *clk; struct regmap *regmap; + spinlock_t lock; u8 id; u8 parent_id; u32 div; @@ -82,41 +83,69 @@ struct isc_subdev_entity { struct v4l2_subdev *sd; struct v4l2_async_subdev *asd; struct v4l2_async_notifier notifier; - struct v4l2_subdev_pad_config *config; u32 pfe_cfg0; struct list_head list; }; +/* Indicate the format is generated by the sensor */ +#define FMT_FLAG_FROM_SENSOR BIT(0) +/* Indicate the format is produced by ISC itself */ +#define FMT_FLAG_FROM_CONTROLLER BIT(1) +/* Indicate a Raw Bayer format */ +#define FMT_FLAG_RAW_FORMAT BIT(2) + +#define FMT_FLAG_RAW_FROM_SENSOR (FMT_FLAG_FROM_SENSOR | \ + FMT_FLAG_RAW_FORMAT) + /* * struct isc_format - ISC media bus format information * @fourcc: Fourcc code for this format * @mbus_code: V4L2 media bus format code. + * flags: Indicate format from sensor or converted by controller * @bpp: Bits per pixel (when stored in memory) - * @reg_bps: reg value for bits per sample * (when transferred over a bus) - * @pipeline: pipeline switch * @sd_support: Subdev supports this format * @isc_support: ISC can convert raw format to this format */ + struct isc_format { u32 fourcc; u32 mbus_code; + u32 flags; u8 bpp; - u32 reg_bps; - u32 reg_bay_cfg; - u32 reg_rlp_mode; - u32 reg_dcfg_imode; - u32 reg_dctrl_dview; - - u32 pipeline; - bool sd_support; bool isc_support; }; +/* Pipeline bitmap */ +#define WB_ENABLE BIT(0) +#define CFA_ENABLE BIT(1) +#define CC_ENABLE BIT(2) +#define GAM_ENABLE BIT(3) +#define GAM_BENABLE BIT(4) +#define GAM_GENABLE BIT(5) +#define GAM_RENABLE BIT(6) +#define CSC_ENABLE BIT(7) +#define CBC_ENABLE BIT(8) +#define SUB422_ENABLE BIT(9) +#define SUB420_ENABLE BIT(10) + +#define GAM_ENABLES (GAM_RENABLE | GAM_GENABLE | GAM_BENABLE | GAM_ENABLE) + +struct fmt_config { + u32 fourcc; + + u32 pfe_cfg0_bps; + u32 cfa_baycfg; + u32 rlp_cfg_mode; + u32 dcfg_imode; + u32 dctrl_dview; + + u32 bits_pipeline; +}; #define HIST_ENTRIES 512 #define HIST_BAYER (ISC_HIS_CFG_MODE_B + 1) @@ -181,80 +210,320 @@ struct isc_device { struct list_head subdev_entities; }; -#define RAW_FMT_IND_START 0 -#define RAW_FMT_IND_END 11 -#define ISC_FMT_IND_START 12 -#define ISC_FMT_IND_END 14 - -static struct isc_format isc_formats[] = { - { V4L2_PIX_FMT_SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - - { V4L2_PIX_FMT_SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - - { V4L2_PIX_FMT_SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12, 16, - ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT12, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG12, MEDIA_BUS_FMT_SGBRG12_1X12, 16, - ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT12, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGRBG12, MEDIA_BUS_FMT_SGRBG12_1X12, 16, - ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT12, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SRGGB12, MEDIA_BUS_FMT_SRGGB12_1X12, 16, - ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT12, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - - { V4L2_PIX_FMT_YUV420, 0x0, 12, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_YYCC, - ISC_DCFG_IMODE_YC420P, ISC_DCTRL_DVIEW_PLANAR, 0x7fb, - false, false }, - { V4L2_PIX_FMT_YUV422P, 0x0, 16, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_YYCC, - ISC_DCFG_IMODE_YC422P, ISC_DCTRL_DVIEW_PLANAR, 0x3fb, - false, false }, - { V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_RGB565_2X8_LE, 16, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_RGB565, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x7b, - false, false }, - - { V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_YUYV8_2X8, 16, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, +static struct isc_format formats_list[] = { + { + .fourcc = V4L2_PIX_FMT_SBGGR8, + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 8, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 8, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 8, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 8, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG10, + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG10, + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB10, + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR12, + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG12, + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG12, + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB12, + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, + .flags = FMT_FLAG_RAW_FROM_SENSOR, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_YUV420, + .mbus_code = 0x0, + .flags = FMT_FLAG_FROM_CONTROLLER, + .bpp = 12, + }, + { + .fourcc = V4L2_PIX_FMT_YUV422P, + .mbus_code = 0x0, + .flags = FMT_FLAG_FROM_CONTROLLER, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_GREY, + .mbus_code = MEDIA_BUS_FMT_Y8_1X8, + .flags = FMT_FLAG_FROM_CONTROLLER | + FMT_FLAG_FROM_SENSOR, + .bpp = 8, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB444, + .mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, + .flags = FMT_FLAG_FROM_CONTROLLER, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB555, + .mbus_code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, + .flags = FMT_FLAG_FROM_CONTROLLER, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_RGB565, + .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE, + .flags = FMT_FLAG_FROM_CONTROLLER, + .bpp = 16, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB32, + .mbus_code = MEDIA_BUS_FMT_ARGB8888_1X32, + .flags = FMT_FLAG_FROM_CONTROLLER, + .bpp = 32, + }, + { + .fourcc = V4L2_PIX_FMT_YUYV, + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, + .flags = FMT_FLAG_FROM_CONTROLLER | + FMT_FLAG_FROM_SENSOR, + .bpp = 16, + }, +}; + +struct fmt_config fmt_configs_list[] = { + { + .fourcc = V4L2_PIX_FMT_SBGGR8, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8, + .dcfg_imode = ISC_DCFG_IMODE_PACKED8, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_GBGB, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8, + .dcfg_imode = ISC_DCFG_IMODE_PACKED8, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_GRGR, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8, + .dcfg_imode = ISC_DCFG_IMODE_PACKED8, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_RGRG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8, + .dcfg_imode = ISC_DCFG_IMODE_PACKED8, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG10, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, + .cfa_baycfg = ISC_BAY_CFG_GBGB, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG10, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, + .cfa_baycfg = ISC_BAY_CFG_GRGR, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB10, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, + .cfa_baycfg = ISC_BAY_CFG_RGRG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR12, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG12, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, + .cfa_baycfg = ISC_BAY_CFG_GBGB, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0 + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG12, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, + .cfa_baycfg = ISC_BAY_CFG_GRGR, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB12, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, + .cfa_baycfg = ISC_BAY_CFG_RGRG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0, + }, + { + .fourcc = V4L2_PIX_FMT_YUV420, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC, + .dcfg_imode = ISC_DCFG_IMODE_YC420P, + .dctrl_dview = ISC_DCTRL_DVIEW_PLANAR, + .bits_pipeline = SUB420_ENABLE | SUB422_ENABLE | + CBC_ENABLE | CSC_ENABLE | + GAM_ENABLES | + CFA_ENABLE | WB_ENABLE, + }, + { + .fourcc = V4L2_PIX_FMT_YUV422P, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC, + .dcfg_imode = ISC_DCFG_IMODE_YC422P, + .dctrl_dview = ISC_DCTRL_DVIEW_PLANAR, + .bits_pipeline = SUB422_ENABLE | + CBC_ENABLE | CSC_ENABLE | + GAM_ENABLES | + CFA_ENABLE | WB_ENABLE, + }, + { + .fourcc = V4L2_PIX_FMT_GREY, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DATY8, + .dcfg_imode = ISC_DCFG_IMODE_PACKED8, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = CBC_ENABLE | CSC_ENABLE | + GAM_ENABLES | + CFA_ENABLE | WB_ENABLE, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB444, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB444, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = GAM_ENABLES | CFA_ENABLE | WB_ENABLE, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB555, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB555, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = GAM_ENABLES | CFA_ENABLE | WB_ENABLE, + }, + { + .fourcc = V4L2_PIX_FMT_RGB565, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_RGB565, + .dcfg_imode = ISC_DCFG_IMODE_PACKED16, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = GAM_ENABLES | CFA_ENABLE | WB_ENABLE, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB32, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB32, + .dcfg_imode = ISC_DCFG_IMODE_PACKED32, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = GAM_ENABLES | CFA_ENABLE | WB_ENABLE, + }, + { + .fourcc = V4L2_PIX_FMT_YUYV, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_BGBG, + .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8, + .dcfg_imode = ISC_DCFG_IMODE_PACKED8, + .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, + .bits_pipeline = 0x0 + }, }; #define GAMMA_MAX 2 @@ -307,31 +576,80 @@ module_param(sensor_preferred, uint, 0644); MODULE_PARM_DESC(sensor_preferred, "Sensor is preferred to output the specified format (1-on 0-off), default 1"); +static int isc_wait_clk_stable(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + struct regmap *regmap = isc_clk->regmap; + unsigned long timeout = jiffies + usecs_to_jiffies(1000); + unsigned int status; + + while (time_before(jiffies, timeout)) { + regmap_read(regmap, ISC_CLKSR, &status); + if (!(status & ISC_CLKSR_SIP)) + return 0; + + usleep_range(10, 250); + } + + return -ETIMEDOUT; +} + +static int isc_clk_prepare(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + + if (isc_clk->id == ISC_ISPCK) + pm_runtime_get_sync(isc_clk->dev); + + return isc_wait_clk_stable(hw); +} + +static void isc_clk_unprepare(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + + isc_wait_clk_stable(hw); + + if (isc_clk->id == ISC_ISPCK) + pm_runtime_put_sync(isc_clk->dev); +} + static int isc_clk_enable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; struct regmap *regmap = isc_clk->regmap; + unsigned long flags; + unsigned int status; dev_dbg(isc_clk->dev, "ISC CLK: %s, div = %d, parent id = %d\n", __func__, isc_clk->div, isc_clk->parent_id); + spin_lock_irqsave(&isc_clk->lock, flags); regmap_update_bits(regmap, ISC_CLKCFG, ISC_CLKCFG_DIV_MASK(id) | ISC_CLKCFG_SEL_MASK(id), (isc_clk->div << ISC_CLKCFG_DIV_SHIFT(id)) | (isc_clk->parent_id << ISC_CLKCFG_SEL_SHIFT(id))); regmap_write(regmap, ISC_CLKEN, ISC_CLK(id)); + spin_unlock_irqrestore(&isc_clk->lock, flags); - return 0; + regmap_read(regmap, ISC_CLKSR, &status); + if (status & ISC_CLK(id)) + return 0; + else + return -EINVAL; } static void isc_clk_disable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; + unsigned long flags; + spin_lock_irqsave(&isc_clk->lock, flags); regmap_write(isc_clk->regmap, ISC_CLKDIS, ISC_CLK(id)); + spin_unlock_irqrestore(&isc_clk->lock, flags); } static int isc_clk_is_enabled(struct clk_hw *hw) @@ -339,8 +657,14 @@ static int isc_clk_is_enabled(struct clk_hw *hw) struct isc_clk *isc_clk = to_isc_clk(hw); u32 status; + if (isc_clk->id == ISC_ISPCK) + pm_runtime_get_sync(isc_clk->dev); + regmap_read(isc_clk->regmap, ISC_CLKSR, &status); + if (isc_clk->id == ISC_ISPCK) + pm_runtime_put_sync(isc_clk->dev); + return status & ISC_CLK(isc_clk->id) ? 1 : 0; } @@ -447,6 +771,8 @@ static int isc_clk_set_rate(struct clk_hw *hw, } static const struct clk_ops isc_clk_ops = { + .prepare = isc_clk_prepare, + .unprepare = isc_clk_unprepare, .enable = isc_clk_enable, .disable = isc_clk_disable, .is_enabled = isc_clk_is_enabled, @@ -492,6 +818,7 @@ static int isc_clk_register(struct isc_device *isc, unsigned int id) isc_clk->regmap = regmap; isc_clk->id = id; isc_clk->dev = isc->dev; + spin_lock_init(&isc_clk->lock); isc_clk->clk = clk_register(isc->dev, &isc_clk->hw); if (IS_ERR(isc_clk->clk)) { @@ -575,11 +902,27 @@ static inline bool sensor_is_preferred(const struct isc_format *isc_fmt) !isc_fmt->isc_support; } +static struct fmt_config *get_fmt_config(u32 fourcc) +{ + struct fmt_config *config; + int i; + + config = &fmt_configs_list[0]; + for (i = 0; i < ARRAY_SIZE(fmt_configs_list); i++) { + if (config->fourcc == fourcc) + return config; + + config++; + } + return NULL; +} + static void isc_start_dma(struct isc_device *isc) { struct regmap *regmap = isc->regmap; struct v4l2_pix_format *pixfmt = &isc->fmt.fmt.pix; u32 sizeimage = pixfmt->sizeimage; + struct fmt_config *config = get_fmt_config(isc->current_fmt->fourcc); u32 dctrl_dview; dma_addr_t addr0; @@ -602,7 +945,7 @@ static void isc_start_dma(struct isc_device *isc) if (sensor_is_preferred(isc->current_fmt)) dctrl_dview = ISC_DCTRL_DVIEW_PACKED; else - dctrl_dview = isc->current_fmt->reg_dctrl_dview; + dctrl_dview = config->dctrl_dview; regmap_write(regmap, ISC_DCTRL, dctrl_dview | ISC_DCTRL_IE_IS); regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_CAPTURE); @@ -612,6 +955,7 @@ static void isc_set_pipeline(struct isc_device *isc, u32 pipeline) { struct regmap *regmap = isc->regmap; struct isc_ctrls *ctrls = &isc->ctrls; + struct fmt_config *config = get_fmt_config(isc->raw_fmt->fourcc); u32 val, bay_cfg; const u32 *gamma; unsigned int i; @@ -625,7 +969,7 @@ static void isc_set_pipeline(struct isc_device *isc, u32 pipeline) if (!pipeline) return; - bay_cfg = isc->raw_fmt->reg_bay_cfg; + bay_cfg = config->cfa_baycfg; regmap_write(regmap, ISC_WB_CFG, bay_cfg); regmap_write(regmap, ISC_WB_O_RGR, 0x0); @@ -678,11 +1022,13 @@ static void isc_set_histogram(struct isc_device *isc) { struct regmap *regmap = isc->regmap; struct isc_ctrls *ctrls = &isc->ctrls; + struct fmt_config *config = get_fmt_config(isc->raw_fmt->fourcc); if (ctrls->awb && (ctrls->hist_stat != HIST_ENABLED)) { - regmap_write(regmap, ISC_HIS_CFG, ISC_HIS_CFG_MODE_R | - (isc->raw_fmt->reg_bay_cfg << ISC_HIS_CFG_BAYSEL_SHIFT) | - ISC_HIS_CFG_RAR); + regmap_write(regmap, ISC_HIS_CFG, + ISC_HIS_CFG_MODE_R | + (config->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT) | + ISC_HIS_CFG_RAR); regmap_write(regmap, ISC_HIS_CTRL, ISC_HIS_CTRL_EN); regmap_write(regmap, ISC_INTEN, ISC_INT_HISDONE); ctrls->hist_id = ISC_HIS_CFG_MODE_R; @@ -699,8 +1045,10 @@ static void isc_set_histogram(struct isc_device *isc) } static inline void isc_get_param(const struct isc_format *fmt, - u32 *rlp_mode, u32 *dcfg) + u32 *rlp_mode, u32 *dcfg) { + struct fmt_config *config = get_fmt_config(fmt->fourcc); + *dcfg = ISC_DCFG_YMBSIZE_BEATS8; switch (fmt->fourcc) { @@ -712,8 +1060,8 @@ static inline void isc_get_param(const struct isc_format *fmt, case V4L2_PIX_FMT_SGBRG12: case V4L2_PIX_FMT_SGRBG12: case V4L2_PIX_FMT_SRGGB12: - *rlp_mode = fmt->reg_rlp_mode; - *dcfg |= fmt->reg_dcfg_imode; + *rlp_mode = config->rlp_cfg_mode; + *dcfg |= config->dcfg_imode; break; default: *rlp_mode = ISC_RLP_CFG_MODE_DAT8; @@ -726,20 +1074,22 @@ static int isc_configure(struct isc_device *isc) { struct regmap *regmap = isc->regmap; const struct isc_format *current_fmt = isc->current_fmt; + struct fmt_config *curfmt_config = get_fmt_config(current_fmt->fourcc); + struct fmt_config *rawfmt_config = get_fmt_config(isc->raw_fmt->fourcc); struct isc_subdev_entity *subdev = isc->current_subdev; u32 pfe_cfg0, rlp_mode, dcfg, mask, pipeline; if (sensor_is_preferred(current_fmt)) { - pfe_cfg0 = current_fmt->reg_bps; + pfe_cfg0 = curfmt_config->pfe_cfg0_bps; pipeline = 0x0; isc_get_param(current_fmt, &rlp_mode, &dcfg); isc->ctrls.hist_stat = HIST_INIT; } else { - pfe_cfg0 = isc->raw_fmt->reg_bps; - pipeline = current_fmt->pipeline; - rlp_mode = current_fmt->reg_rlp_mode; - dcfg = current_fmt->reg_dcfg_imode | ISC_DCFG_YMBSIZE_BEATS8 | - ISC_DCFG_CMBSIZE_BEATS8; + pfe_cfg0 = rawfmt_config->pfe_cfg0_bps; + pipeline = curfmt_config->bits_pipeline; + rlp_mode = curfmt_config->rlp_cfg_mode; + dcfg = curfmt_config->dcfg_imode | + ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8; } pfe_cfg0 |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE; @@ -941,6 +1291,7 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, { struct isc_format *isc_fmt; struct v4l2_pix_format *pixfmt = &f->fmt.pix; + struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_TRY, }; @@ -971,7 +1322,7 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, v4l2_fill_mbus_format(&format.format, pixfmt, mbus_code); ret = v4l2_subdev_call(isc->current_subdev->sd, pad, set_fmt, - isc->current_subdev->config, &format); + &pad_cfg, &format); if (ret < 0) return ret; @@ -1323,6 +1674,7 @@ static void isc_awb_work(struct work_struct *w) struct isc_device *isc = container_of(w, struct isc_device, awb_work); struct regmap *regmap = isc->regmap; + struct fmt_config *config = get_fmt_config(isc->raw_fmt->fourcc); struct isc_ctrls *ctrls = &isc->ctrls; u32 hist_id = ctrls->hist_id; u32 baysel; @@ -1340,7 +1692,7 @@ static void isc_awb_work(struct work_struct *w) } ctrls->hist_id = hist_id; - baysel = isc->raw_fmt->reg_bay_cfg << ISC_HIS_CFG_BAYSEL_SHIFT; + baysel = config->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT; pm_runtime_get_sync(isc->dev); @@ -1436,17 +1788,15 @@ static void isc_async_unbind(struct v4l2_async_notifier *notifier, struct isc_device, v4l2_dev); cancel_work_sync(&isc->awb_work); video_unregister_device(&isc->video_dev); - if (isc->current_subdev->config) - v4l2_subdev_free_pad_config(isc->current_subdev->config); v4l2_ctrl_handler_free(&isc->ctrls.handler); } static struct isc_format *find_format_by_code(unsigned int code, int *index) { - struct isc_format *fmt = &isc_formats[0]; + struct isc_format *fmt = &formats_list[0]; unsigned int i; - for (i = 0; i < ARRAY_SIZE(isc_formats); i++) { + for (i = 0; i < ARRAY_SIZE(formats_list); i++) { if (fmt->mbus_code == code) { *index = i; return fmt; @@ -1463,37 +1813,36 @@ static int isc_formats_init(struct isc_device *isc) struct isc_format *fmt; struct v4l2_subdev *subdev = isc->current_subdev->sd; unsigned int num_fmts, i, j; + u32 list_size = ARRAY_SIZE(formats_list); struct v4l2_subdev_mbus_code_enum mbus_code = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; - fmt = &isc_formats[0]; - for (i = 0; i < ARRAY_SIZE(isc_formats); i++) { - fmt->isc_support = false; - fmt->sd_support = false; - - fmt++; - } - while (!v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &mbus_code)) { mbus_code.index++; + fmt = find_format_by_code(mbus_code.code, &i); - if (!fmt) + if ((!fmt) || (!(fmt->flags & FMT_FLAG_FROM_SENSOR))) continue; fmt->sd_support = true; - if (i <= RAW_FMT_IND_END) { - for (j = ISC_FMT_IND_START; j <= ISC_FMT_IND_END; j++) - isc_formats[j].isc_support = true; - + if (fmt->flags & FMT_FLAG_RAW_FORMAT) isc->raw_fmt = fmt; - } } - fmt = &isc_formats[0]; - for (i = 0, num_fmts = 0; i < ARRAY_SIZE(isc_formats); i++) { + fmt = &formats_list[0]; + for (i = 0; i < list_size; i++) { + if (fmt->flags & FMT_FLAG_FROM_CONTROLLER) + fmt->isc_support = true; + + fmt++; + } + + fmt = &formats_list[0]; + num_fmts = 0; + for (i = 0; i < list_size; i++) { if (fmt->isc_support || fmt->sd_support) num_fmts++; @@ -1505,15 +1854,13 @@ static int isc_formats_init(struct isc_device *isc) isc->num_user_formats = num_fmts; isc->user_formats = devm_kcalloc(isc->dev, - num_fmts, sizeof(struct isc_format *), + num_fmts, sizeof(*isc->user_formats), GFP_KERNEL); - if (!isc->user_formats) { - v4l2_err(&isc->v4l2_dev, "could not allocate memory\n"); + if (!isc->user_formats) return -ENOMEM; - } - fmt = &isc_formats[0]; - for (i = 0, j = 0; i < ARRAY_SIZE(isc_formats); i++) { + fmt = &formats_list[0]; + for (i = 0, j = 0; i < list_size; i++) { if (fmt->isc_support || fmt->sd_support) isc->user_formats[j++] = fmt; @@ -1550,7 +1897,6 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) { struct isc_device *isc = container_of(notifier->v4l2_dev, struct isc_device, v4l2_dev); - struct isc_subdev_entity *sd_entity; struct video_device *vdev = &isc->video_dev; struct vb2_queue *q = &isc->vb2_vidq; int ret; @@ -1563,8 +1909,6 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) isc->current_subdev = container_of(notifier, struct isc_subdev_entity, notifier); - sd_entity = isc->current_subdev; - mutex_init(&isc->lock); init_completion(&isc->comp); @@ -1591,10 +1935,6 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) INIT_LIST_HEAD(&isc->dma_queue); spin_lock_init(&isc->dma_queue_lock); - sd_entity->config = v4l2_subdev_alloc_pad_config(sd_entity->sd); - if (sd_entity->config == NULL) - return -ENOMEM; - ret = isc_formats_init(isc); if (ret < 0) { v4l2_err(&isc->v4l2_dev, @@ -1639,6 +1979,12 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) return 0; } +static const struct v4l2_async_notifier_operations isc_async_ops = { + .bound = isc_async_bound, + .unbind = isc_async_unbind, + .complete = isc_async_complete, +}; + static void isc_subdev_cleanup(struct isc_device *isc) { struct isc_subdev_entity *subdev_entity; @@ -1716,7 +2062,7 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc) subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity), GFP_KERNEL); - if (subdev_entity == NULL) { + if (!subdev_entity) { of_node_put(rem); ret = -ENOMEM; break; @@ -1724,7 +2070,7 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc) subdev_entity->asd = devm_kzalloc(dev, sizeof(*subdev_entity->asd), GFP_KERNEL); - if (subdev_entity->asd == NULL) { + if (!subdev_entity->asd) { of_node_put(rem); ret = -ENOMEM; break; @@ -1815,25 +2161,37 @@ static int atmel_isc_probe(struct platform_device *pdev) return ret; } + ret = clk_prepare_enable(isc->hclock); + if (ret) { + dev_err(dev, "failed to enable hclock: %d\n", ret); + return ret; + } + ret = isc_clk_init(isc); if (ret) { dev_err(dev, "failed to init isc clock: %d\n", ret); - goto clean_isc_clk; + goto unprepare_hclk; } isc->ispck = isc->isc_clks[ISC_ISPCK].clk; + ret = clk_prepare_enable(isc->ispck); + if (ret) { + dev_err(dev, "failed to enable ispck: %d\n", ret); + goto unprepare_hclk; + } + /* ispck should be greater or equal to hclock */ ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); if (ret) { dev_err(dev, "failed to set ispck rate: %d\n", ret); - goto clean_isc_clk; + goto unprepare_clk; } ret = v4l2_device_register(dev, &isc->v4l2_dev); if (ret) { dev_err(dev, "unable to register v4l2 device.\n"); - goto clean_isc_clk; + goto unprepare_clk; } ret = isc_parse_dt(dev, isc); @@ -1851,9 +2209,7 @@ static int atmel_isc_probe(struct platform_device *pdev) list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { subdev_entity->notifier.subdevs = &subdev_entity->asd; subdev_entity->notifier.num_subdevs = 1; - subdev_entity->notifier.bound = isc_async_bound; - subdev_entity->notifier.unbind = isc_async_unbind; - subdev_entity->notifier.complete = isc_async_complete; + subdev_entity->notifier.ops = &isc_async_ops; ret = v4l2_async_notifier_register(&isc->v4l2_dev, &subdev_entity->notifier); @@ -1866,7 +2222,9 @@ static int atmel_isc_probe(struct platform_device *pdev) break; } + pm_runtime_set_active(dev); pm_runtime_enable(dev); + pm_request_idle(dev); return 0; @@ -1876,7 +2234,11 @@ cleanup_subdev: unregister_v4l2_device: v4l2_device_unregister(&isc->v4l2_dev); -clean_isc_clk: +unprepare_clk: + clk_disable_unprepare(isc->ispck); +unprepare_hclk: + clk_disable_unprepare(isc->hclock); + isc_clk_cleanup(isc); return ret; @@ -1887,6 +2249,8 @@ static int atmel_isc_remove(struct platform_device *pdev) struct isc_device *isc = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); + clk_disable_unprepare(isc->ispck); + clk_disable_unprepare(isc->hclock); isc_subdev_cleanup(isc); diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c index 891fa2505efa..e900995143a3 100644 --- a/drivers/media/platform/atmel/atmel-isi.c +++ b/drivers/media/platform/atmel/atmel-isi.c @@ -411,7 +411,7 @@ static void buffer_queue(struct vb2_buffer *vb) spin_lock_irqsave(&isi->irqlock, flags); list_add_tail(&buf->list, &isi->video_buffer_list); - if (isi->active == NULL) { + if (!isi->active) { isi->active = buf; if (vb2_is_streaming(vb->vb2_queue)) start_dma(isi, buf); @@ -1038,10 +1038,8 @@ static int isi_formats_init(struct atmel_isi *isi) isi->user_formats = devm_kcalloc(isi->dev, num_fmts, sizeof(struct isi_format *), GFP_KERNEL); - if (!isi->user_formats) { - dev_err(isi->dev, "could not allocate memory\n"); + if (!isi->user_formats) return -ENOMEM; - } memcpy(isi->user_formats, isi_fmts, num_fmts * sizeof(struct isi_format *)); @@ -1105,6 +1103,12 @@ static int isi_graph_notify_bound(struct v4l2_async_notifier *notifier, return 0; } +static const struct v4l2_async_notifier_operations isi_graph_notify_ops = { + .bound = isi_graph_notify_bound, + .unbind = isi_graph_notify_unbind, + .complete = isi_graph_notify_complete, +}; + static int isi_graph_parse(struct atmel_isi *isi, struct device_node *node) { struct device_node *ep = NULL; @@ -1143,7 +1147,7 @@ static int isi_graph_init(struct atmel_isi *isi) /* Register the subdevices notifier. */ subdevs = devm_kzalloc(isi->dev, sizeof(*subdevs), GFP_KERNEL); - if (subdevs == NULL) { + if (!subdevs) { of_node_put(isi->entity.node); return -ENOMEM; } @@ -1152,9 +1156,7 @@ static int isi_graph_init(struct atmel_isi *isi) isi->notifier.subdevs = subdevs; isi->notifier.num_subdevs = 1; - isi->notifier.bound = isi_graph_notify_bound; - isi->notifier.unbind = isi_graph_notify_unbind; - isi->notifier.complete = isi_graph_notify_complete; + isi->notifier.ops = &isi_graph_notify_ops; ret = v4l2_async_notifier_register(&isi->v4l2_dev, &isi->notifier); if (ret < 0) { @@ -1176,10 +1178,8 @@ static int atmel_isi_probe(struct platform_device *pdev) int ret, i; isi = devm_kzalloc(&pdev->dev, sizeof(struct atmel_isi), GFP_KERNEL); - if (!isi) { - dev_err(&pdev->dev, "Can't allocate interface!\n"); + if (!isi) return -ENOMEM; - } isi->pclk = devm_clk_get(&pdev->dev, "isi_clk"); if (IS_ERR(isi->pclk)) @@ -1204,7 +1204,7 @@ static int atmel_isi_probe(struct platform_device *pdev) return ret; isi->vdev = video_device_alloc(); - if (isi->vdev == NULL) { + if (!isi->vdev) { ret = -ENOMEM; goto err_vdev_alloc; } diff --git a/drivers/media/platform/blackfin/ppi.c b/drivers/media/platform/blackfin/ppi.c index 37169054b828..478eb2f7d723 100644 --- a/drivers/media/platform/blackfin/ppi.c +++ b/drivers/media/platform/blackfin/ppi.c @@ -338,7 +338,6 @@ struct ppi_if *ppi_create_instance(struct platform_device *pdev, ppi = kzalloc(sizeof(*ppi), GFP_KERNEL); if (!ppi) { peripheral_free_list(info->pin_req); - dev_err(&pdev->dev, "unable to allocate memory for ppi handle\n"); return NULL; } ppi->ops = &ppi_ops; diff --git a/drivers/media/platform/cec-gpio/Makefile b/drivers/media/platform/cec-gpio/Makefile new file mode 100644 index 000000000000..e82b258afa55 --- /dev/null +++ b/drivers/media/platform/cec-gpio/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_CEC_GPIO) += cec-gpio.o diff --git a/drivers/media/platform/cec-gpio/cec-gpio.c b/drivers/media/platform/cec-gpio/cec-gpio.c new file mode 100644 index 000000000000..5debdf08fbe7 --- /dev/null +++ b/drivers/media/platform/cec-gpio/cec-gpio.c @@ -0,0 +1,239 @@ +/* + * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/gpio/consumer.h> +#include <media/cec-pin.h> + +struct cec_gpio { + struct cec_adapter *adap; + struct device *dev; + + struct gpio_desc *cec_gpio; + int cec_irq; + bool cec_is_low; + bool cec_have_irq; + + struct gpio_desc *hpd_gpio; + int hpd_irq; + bool hpd_is_high; + ktime_t hpd_ts; +}; + +static bool cec_gpio_read(struct cec_adapter *adap) +{ + struct cec_gpio *cec = cec_get_drvdata(adap); + + if (cec->cec_is_low) + return false; + return gpiod_get_value(cec->cec_gpio); +} + +static void cec_gpio_high(struct cec_adapter *adap) +{ + struct cec_gpio *cec = cec_get_drvdata(adap); + + if (!cec->cec_is_low) + return; + cec->cec_is_low = false; + gpiod_set_value(cec->cec_gpio, 1); +} + +static void cec_gpio_low(struct cec_adapter *adap) +{ + struct cec_gpio *cec = cec_get_drvdata(adap); + + if (cec->cec_is_low) + return; + if (WARN_ON_ONCE(cec->cec_have_irq)) + free_irq(cec->cec_irq, cec); + cec->cec_have_irq = false; + cec->cec_is_low = true; + gpiod_set_value(cec->cec_gpio, 0); +} + +static irqreturn_t cec_hpd_gpio_irq_handler_thread(int irq, void *priv) +{ + struct cec_gpio *cec = priv; + + cec_queue_pin_hpd_event(cec->adap, cec->hpd_is_high, cec->hpd_ts); + return IRQ_HANDLED; +} + +static irqreturn_t cec_hpd_gpio_irq_handler(int irq, void *priv) +{ + struct cec_gpio *cec = priv; + bool is_high = gpiod_get_value(cec->hpd_gpio); + + if (is_high == cec->hpd_is_high) + return IRQ_HANDLED; + cec->hpd_ts = ktime_get(); + cec->hpd_is_high = is_high; + return IRQ_WAKE_THREAD; +} + +static irqreturn_t cec_gpio_irq_handler(int irq, void *priv) +{ + struct cec_gpio *cec = priv; + + cec_pin_changed(cec->adap, gpiod_get_value(cec->cec_gpio)); + return IRQ_HANDLED; +} + +static bool cec_gpio_enable_irq(struct cec_adapter *adap) +{ + struct cec_gpio *cec = cec_get_drvdata(adap); + + if (cec->cec_have_irq) + return true; + + if (request_irq(cec->cec_irq, cec_gpio_irq_handler, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + adap->name, cec)) + return false; + cec->cec_have_irq = true; + return true; +} + +static void cec_gpio_disable_irq(struct cec_adapter *adap) +{ + struct cec_gpio *cec = cec_get_drvdata(adap); + + if (cec->cec_have_irq) + free_irq(cec->cec_irq, cec); + cec->cec_have_irq = false; +} + +static void cec_gpio_status(struct cec_adapter *adap, struct seq_file *file) +{ + struct cec_gpio *cec = cec_get_drvdata(adap); + + seq_printf(file, "mode: %s\n", cec->cec_is_low ? "low-drive" : "read"); + if (cec->cec_have_irq) + seq_printf(file, "using irq: %d\n", cec->cec_irq); + if (cec->hpd_gpio) + seq_printf(file, "hpd: %s\n", + cec->hpd_is_high ? "high" : "low"); +} + +static int cec_gpio_read_hpd(struct cec_adapter *adap) +{ + struct cec_gpio *cec = cec_get_drvdata(adap); + + if (!cec->hpd_gpio) + return -ENOTTY; + return gpiod_get_value(cec->hpd_gpio); +} + +static void cec_gpio_free(struct cec_adapter *adap) +{ + cec_gpio_disable_irq(adap); +} + +static const struct cec_pin_ops cec_gpio_pin_ops = { + .read = cec_gpio_read, + .low = cec_gpio_low, + .high = cec_gpio_high, + .enable_irq = cec_gpio_enable_irq, + .disable_irq = cec_gpio_disable_irq, + .status = cec_gpio_status, + .free = cec_gpio_free, + .read_hpd = cec_gpio_read_hpd, +}; + +static int cec_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cec_gpio *cec; + int ret; + + cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL); + if (!cec) + return -ENOMEM; + + cec->dev = dev; + + cec->cec_gpio = devm_gpiod_get(dev, "cec", GPIOD_IN); + if (IS_ERR(cec->cec_gpio)) + return PTR_ERR(cec->cec_gpio); + cec->cec_irq = gpiod_to_irq(cec->cec_gpio); + + cec->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN); + if (IS_ERR(cec->hpd_gpio)) + return PTR_ERR(cec->hpd_gpio); + + cec->adap = cec_pin_allocate_adapter(&cec_gpio_pin_ops, + cec, pdev->name, CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR | + CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN); + if (IS_ERR(cec->adap)) + return PTR_ERR(cec->adap); + + if (cec->hpd_gpio) { + cec->hpd_irq = gpiod_to_irq(cec->hpd_gpio); + ret = devm_request_threaded_irq(dev, cec->hpd_irq, + cec_hpd_gpio_irq_handler, + cec_hpd_gpio_irq_handler_thread, + IRQF_ONESHOT | + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "hpd-gpio", cec); + if (ret) + return ret; + } + + ret = cec_register_adapter(cec->adap, &pdev->dev); + if (ret) { + cec_delete_adapter(cec->adap); + return ret; + } + + platform_set_drvdata(pdev, cec); + return 0; +} + +static int cec_gpio_remove(struct platform_device *pdev) +{ + struct cec_gpio *cec = platform_get_drvdata(pdev); + + cec_unregister_adapter(cec->adap); + return 0; +} + +static const struct of_device_id cec_gpio_match[] = { + { + .compatible = "cec-gpio", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, cec_gpio_match); + +static struct platform_driver cec_gpio_pdrv = { + .probe = cec_gpio_probe, + .remove = cec_gpio_remove, + .driver = { + .name = "cec-gpio", + .of_match_table = cec_gpio_match, + }, +}; + +module_platform_driver(cec_gpio_pdrv); + +MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("CEC GPIO driver"); diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 291c40933935..bfc4ecf6f068 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -417,6 +417,10 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, dev->devtype->product != CODA_DX6) size += ysize / 4; name = kasprintf(GFP_KERNEL, "fb%d", i); + if (!name) { + coda_free_framebuffers(ctx); + return -ENOMEM; + } ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], size, name); kfree(name); diff --git a/drivers/media/platform/davinci/ccdc_hw_device.h b/drivers/media/platform/davinci/ccdc_hw_device.h index f1b521045d64..3482178cbf01 100644 --- a/drivers/media/platform/davinci/ccdc_hw_device.h +++ b/drivers/media/platform/davinci/ccdc_hw_device.h @@ -82,8 +82,8 @@ struct ccdc_hw_device { }; /* Used by CCDC module to register & unregister with vpfe capture driver */ -int vpfe_register_ccdc_device(struct ccdc_hw_device *dev); -void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev); +int vpfe_register_ccdc_device(const struct ccdc_hw_device *dev); +void vpfe_unregister_ccdc_device(const struct ccdc_hw_device *dev); #endif #endif diff --git a/drivers/media/platform/davinci/dm355_ccdc.c b/drivers/media/platform/davinci/dm355_ccdc.c index 6d492dc4c3a9..89cb3094d7e6 100644 --- a/drivers/media/platform/davinci/dm355_ccdc.c +++ b/drivers/media/platform/davinci/dm355_ccdc.c @@ -841,7 +841,7 @@ static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) return 0; } -static struct ccdc_hw_device ccdc_hw_dev = { +static const struct ccdc_hw_device ccdc_hw_dev = { .name = "DM355 CCDC", .owner = THIS_MODULE, .hw_ops = { diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c index 3b2d8a9317b8..5fa0a1f32536 100644 --- a/drivers/media/platform/davinci/dm644x_ccdc.c +++ b/drivers/media/platform/davinci/dm644x_ccdc.c @@ -776,7 +776,7 @@ static void ccdc_restore_context(void) regw(ccdc_ctx[CCDC_VP_OUT >> 2], CCDC_VP_OUT); regw(ccdc_ctx[CCDC_PCR >> 2], CCDC_PCR); } -static struct ccdc_hw_device ccdc_hw_dev = { +static const struct ccdc_hw_device ccdc_hw_dev = { .name = "DM6446 CCDC", .owner = THIS_MODULE, .hw_ops = { diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c index 5813b49391ed..d5ff58494c1e 100644 --- a/drivers/media/platform/davinci/isif.c +++ b/drivers/media/platform/davinci/isif.c @@ -1000,7 +1000,7 @@ static int isif_close(struct device *device) return 0; } -static struct ccdc_hw_device isif_hw_dev = { +static const struct ccdc_hw_device isif_hw_dev = { .name = "ISIF", .owner = THIS_MODULE, .hw_ops = { diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 13d027031ff0..6aabd21fe69f 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -122,7 +122,7 @@ static irqreturn_t venc_isr(int irq, void *arg) int fid; int i; - if ((NULL == arg) || (NULL == disp_dev->dev[0])) + if (!arg || !disp_dev->dev[0]) return IRQ_HANDLED; if (venc_is_second_field(disp_dev)) @@ -337,10 +337,10 @@ static void vpbe_stop_streaming(struct vb2_queue *vq) vb2_buffer_done(&layer->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); } else { - if (layer->cur_frm != NULL) + if (layer->cur_frm) vb2_buffer_done(&layer->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); - if (layer->next_frm != NULL) + if (layer->next_frm) vb2_buffer_done(&layer->next_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); } @@ -947,7 +947,7 @@ static int vpbe_display_s_std(struct file *file, void *priv, if (vb2_is_busy(&layer->buffer_queue)) return -EBUSY; - if (NULL != vpbe_dev->ops.s_std) { + if (vpbe_dev->ops.s_std) { ret = vpbe_dev->ops.s_std(vpbe_dev, std_id); if (ret) { v4l2_err(&vpbe_dev->v4l2_dev, @@ -1000,8 +1000,7 @@ static int vpbe_display_enum_output(struct file *file, void *priv, v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_OUTPUT\n"); /* Enumerate outputs */ - - if (NULL == vpbe_dev->ops.enum_outputs) + if (!vpbe_dev->ops.enum_outputs) return -EINVAL; ret = vpbe_dev->ops.enum_outputs(vpbe_dev, output); @@ -1030,7 +1029,7 @@ static int vpbe_display_s_output(struct file *file, void *priv, if (vb2_is_busy(&layer->buffer_queue)) return -EBUSY; - if (NULL == vpbe_dev->ops.set_output) + if (!vpbe_dev->ops.set_output) return -EINVAL; ret = vpbe_dev->ops.set_output(vpbe_dev, i); @@ -1077,7 +1076,7 @@ vpbe_display_enum_dv_timings(struct file *file, void *priv, v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_TIMINGS\n"); /* Enumerate outputs */ - if (NULL == vpbe_dev->ops.enum_dv_timings) + if (!vpbe_dev->ops.enum_dv_timings) return -EINVAL; ret = vpbe_dev->ops.enum_dv_timings(vpbe_dev, timings); @@ -1292,7 +1291,7 @@ static int vpbe_device_get(struct device *dev, void *data) if (strcmp("vpbe_controller", pdev->name) == 0) vpbe_disp->vpbe_dev = platform_get_drvdata(pdev); - if (strstr(pdev->name, "vpbe-osd") != NULL) + if (strstr(pdev->name, "vpbe-osd")) vpbe_disp->osd_device = platform_get_drvdata(pdev); return 0; @@ -1305,15 +1304,10 @@ static int init_vpbe_layer(int i, struct vpbe_display *disp_dev, struct video_device *vbd = NULL; /* Allocate memory for four plane display objects */ - - disp_dev->dev[i] = - kzalloc(sizeof(struct vpbe_layer), GFP_KERNEL); - - /* If memory allocation fails, return error */ - if (!disp_dev->dev[i]) { - printk(KERN_ERR "ran out of memory\n"); + disp_dev->dev[i] = kzalloc(sizeof(*disp_dev->dev[i]), GFP_KERNEL); + if (!disp_dev->dev[i]) return -ENOMEM; - } + spin_lock_init(&disp_dev->dev[i]->irqlock); mutex_init(&disp_dev->dev[i]->opslock); @@ -1397,8 +1391,7 @@ static int vpbe_display_probe(struct platform_device *pdev) printk(KERN_DEBUG "vpbe_display_probe\n"); /* Allocate memory for vpbe_display */ - disp_dev = devm_kzalloc(&pdev->dev, sizeof(struct vpbe_display), - GFP_KERNEL); + disp_dev = devm_kzalloc(&pdev->dev, sizeof(*disp_dev), GFP_KERNEL); if (!disp_dev) return -ENOMEM; @@ -1414,7 +1407,7 @@ static int vpbe_display_probe(struct platform_device *pdev) v4l2_dev = &disp_dev->vpbe_dev->v4l2_dev; /* Initialize the vpbe display controller */ - if (NULL != disp_dev->vpbe_dev->ops.initialize) { + if (disp_dev->vpbe_dev->ops.initialize) { err = disp_dev->vpbe_dev->ops.initialize(&pdev->dev, disp_dev->vpbe_dev); if (err) { @@ -1482,7 +1475,7 @@ static int vpbe_display_probe(struct platform_device *pdev) probe_out: for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) { /* Unregister video device */ - if (disp_dev->dev[k] != NULL) { + if (disp_dev->dev[k]) { video_unregister_device(&disp_dev->dev[k]->video_dev); kfree(disp_dev->dev[k]); } @@ -1504,7 +1497,7 @@ static int vpbe_display_remove(struct platform_device *pdev) v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_remove\n"); /* deinitialize the vpbe display controller */ - if (NULL != vpbe_dev->ops.deinitialize) + if (vpbe_dev->ops.deinitialize) vpbe_dev->ops.deinitialize(&pdev->dev, vpbe_dev); /* un-register device */ for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) { diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 6792da16d9c7..7b3f6f8e3dc8 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -115,7 +115,7 @@ static struct vpfe_config_params config_params = { }; /* ccdc device registered */ -static struct ccdc_hw_device *ccdc_dev; +static const struct ccdc_hw_device *ccdc_dev; /* lock for accessing ccdc information */ static DEFINE_MUTEX(ccdc_lock); /* ccdc configuration */ @@ -203,7 +203,7 @@ static const struct vpfe_pixel_format *vpfe_lookup_pix_format(u32 pix_format) * vpfe_register_ccdc_device. CCDC module calls this to * register with vpfe capture */ -int vpfe_register_ccdc_device(struct ccdc_hw_device *dev) +int vpfe_register_ccdc_device(const struct ccdc_hw_device *dev) { int ret = 0; printk(KERN_NOTICE "vpfe_register_ccdc_device: %s\n", dev->name); @@ -259,7 +259,7 @@ EXPORT_SYMBOL(vpfe_register_ccdc_device); * vpfe_unregister_ccdc_device. CCDC module calls this to * unregister with vpfe capture */ -void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev) +void vpfe_unregister_ccdc_device(const struct ccdc_hw_device *dev) { if (!dev) { printk(KERN_ERR "invalid ccdc device ptr\n"); diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c index 07e89a4985a6..16352e2263d2 100644 --- a/drivers/media/platform/davinci/vpif.c +++ b/drivers/media/platform/davinci/vpif.c @@ -47,8 +47,9 @@ EXPORT_SYMBOL_GPL(vpif_lock); void __iomem *vpif_base; EXPORT_SYMBOL_GPL(vpif_base); -/** +/* * vpif_ch_params: video standard configuration parameters for vpif + * * The table must include all presets from supported subdevices. */ const struct vpif_channel_config_params vpif_ch_params[] = { diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 0ef36cec21d1..fca4dc829f73 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -109,7 +109,7 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb) * @vq: vb2_queue ptr * @nbuffers: ptr to number of buffers requested by application * @nplanes:: contains number of distinct video planes needed to hold a frame - * @sizes[]: contains the size (in bytes) of each plane. + * @sizes: contains the size (in bytes) of each plane. * @alloc_devs: ptr to allocation context * * This callback function is called when reqbuf() is called to adjust @@ -167,7 +167,7 @@ static void vpif_buffer_queue(struct vb2_buffer *vb) /** * vpif_start_streaming : Starts the DMA engine for streaming - * @vb: ptr to vb2_buffer + * @vq: ptr to vb2_buffer * @count: number of buffers */ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) @@ -629,7 +629,7 @@ static void vpif_calculate_offsets(struct channel_obj *ch) /** * vpif_get_default_field() - Get default field type based on interface - * @vpif_params - ptr to vpif params + * @iface: ptr to vpif interface */ static inline enum v4l2_field vpif_get_default_field( struct vpif_interface *iface) @@ -640,8 +640,8 @@ static inline enum v4l2_field vpif_get_default_field( /** * vpif_config_addr() - function to configure buffer address in vpif - * @ch - channel ptr - * @muxmode - channel mux mode + * @ch: channel ptr + * @muxmode: channel mux mode */ static void vpif_config_addr(struct channel_obj *ch, int muxmode) { @@ -661,9 +661,9 @@ static void vpif_config_addr(struct channel_obj *ch, int muxmode) /** * vpif_input_to_subdev() - Maps input to sub device - * @vpif_cfg - global config ptr - * @chan_cfg - channel config ptr - * @input_index - Given input index from application + * @vpif_cfg: global config ptr + * @chan_cfg: channel config ptr + * @input_index: Given input index from application * * lookup the sub device information for a given input index. * we report all the inputs to application. inputs table also @@ -699,9 +699,9 @@ static int vpif_input_to_subdev( /** * vpif_set_input() - Select an input - * @vpif_cfg - global config ptr - * @ch - channel - * @_index - Given input index from application + * @vpif_cfg: global config ptr + * @ch: channel + * @index: Given input index from application * * Select the given input. */ @@ -792,7 +792,7 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id) * vpif_g_std() - get STD handler * @file: file ptr * @priv: file handle - * @std_id: ptr to std id + * @std: ptr to std id */ static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std) { @@ -933,7 +933,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) * vpif_enum_fmt_vid_cap() - ENUM_FMT handler * @file: file ptr * @priv: file handle - * @index: input index + * @fmt: ptr to V4L2 format descriptor */ static int vpif_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fmt) @@ -1500,6 +1500,11 @@ static int vpif_async_complete(struct v4l2_async_notifier *notifier) return vpif_probe_complete(); } +static const struct v4l2_async_notifier_operations vpif_async_ops = { + .bound = vpif_async_bound, + .complete = vpif_async_complete, +}; + static struct vpif_capture_config * vpif_capture_get_pdata(struct platform_device *pdev) { @@ -1691,8 +1696,7 @@ static __init int vpif_probe(struct platform_device *pdev) } else { vpif_obj.notifier.subdevs = vpif_obj.config->asd; vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; - vpif_obj.notifier.bound = vpif_async_bound; - vpif_obj.notifier.complete = vpif_async_complete; + vpif_obj.notifier.ops = &vpif_async_ops; err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, &vpif_obj.notifier); if (err) { @@ -1741,6 +1745,7 @@ static int vpif_remove(struct platform_device *device) #ifdef CONFIG_PM_SLEEP /** * vpif_suspend: vpif device suspend + * @dev: pointer to &struct device */ static int vpif_suspend(struct device *dev) { diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 56fe4e5b396e..7be636237acf 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -102,7 +102,7 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb) * @vq: vb2_queue ptr * @nbuffers: ptr to number of buffers requested by application * @nplanes:: contains number of distinct video planes needed to hold a frame - * @sizes[]: contains the size (in bytes) of each plane. + * @sizes: contains the size (in bytes) of each plane. * @alloc_devs: ptr to allocation context * * This callback function is called when reqbuf() is called to adjust @@ -158,7 +158,7 @@ static void vpif_buffer_queue(struct vb2_buffer *vb) /** * vpif_start_streaming : Starts the DMA engine for streaming - * @vb: ptr to vb2_buffer + * @vq: ptr to vb2_buffer * @count: number of buffers */ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) @@ -766,9 +766,9 @@ static int vpif_enum_output(struct file *file, void *fh, /** * vpif_output_to_subdev() - Maps output to sub device - * @vpif_cfg - global config ptr - * @chan_cfg - channel config ptr - * @index - Given output index from application + * @vpif_cfg: global config ptr + * @chan_cfg: channel config ptr + * @index: Given output index from application * * lookup the sub device information for a given output index. * we report all the output to application. output table also @@ -802,9 +802,9 @@ vpif_output_to_subdev(struct vpif_display_config *vpif_cfg, /** * vpif_set_output() - Select an output - * @vpif_cfg - global config ptr - * @ch - channel - * @index - Given output index from application + * @vpif_cfg: global config ptr + * @ch: channel + * @index: Given output index from application * * Select the given output. */ @@ -1232,6 +1232,11 @@ static int vpif_async_complete(struct v4l2_async_notifier *notifier) return vpif_probe_complete(); } +static const struct v4l2_async_notifier_operations vpif_async_ops = { + .bound = vpif_async_bound, + .complete = vpif_async_complete, +}; + /* * vpif_probe: This function creates device entries by register itself to the * V4L2 driver and initializes fields of each channel objects @@ -1313,8 +1318,7 @@ static __init int vpif_probe(struct platform_device *pdev) } else { vpif_obj.notifier.subdevs = vpif_obj.config->asd; vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; - vpif_obj.notifier.bound = vpif_async_bound; - vpif_obj.notifier.complete = vpif_async_complete; + vpif_obj.notifier.ops = &vpif_async_ops; err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, &vpif_obj.notifier); if (err) { diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 43801509dabb..17854a379243 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c @@ -958,6 +958,51 @@ static struct gsc_pix_max gsc_v_100_max = { .target_rot_en_h = 2016, }; +static struct gsc_pix_max gsc_v_5250_max = { + .org_scaler_bypass_w = 8192, + .org_scaler_bypass_h = 8192, + .org_scaler_input_w = 4800, + .org_scaler_input_h = 3344, + .real_rot_dis_w = 4800, + .real_rot_dis_h = 3344, + .real_rot_en_w = 2016, + .real_rot_en_h = 2016, + .target_rot_dis_w = 4800, + .target_rot_dis_h = 3344, + .target_rot_en_w = 2016, + .target_rot_en_h = 2016, +}; + +static struct gsc_pix_max gsc_v_5420_max = { + .org_scaler_bypass_w = 8192, + .org_scaler_bypass_h = 8192, + .org_scaler_input_w = 4800, + .org_scaler_input_h = 3344, + .real_rot_dis_w = 4800, + .real_rot_dis_h = 3344, + .real_rot_en_w = 2048, + .real_rot_en_h = 2048, + .target_rot_dis_w = 4800, + .target_rot_dis_h = 3344, + .target_rot_en_w = 2016, + .target_rot_en_h = 2016, +}; + +static struct gsc_pix_max gsc_v_5433_max = { + .org_scaler_bypass_w = 8192, + .org_scaler_bypass_h = 8192, + .org_scaler_input_w = 4800, + .org_scaler_input_h = 3344, + .real_rot_dis_w = 4800, + .real_rot_dis_h = 3344, + .real_rot_en_w = 2047, + .real_rot_en_h = 2047, + .target_rot_dis_w = 4800, + .target_rot_dis_h = 3344, + .target_rot_en_w = 2016, + .target_rot_en_h = 2016, +}; + static struct gsc_pix_min gsc_v_100_min = { .org_w = 64, .org_h = 32, @@ -992,6 +1037,45 @@ static struct gsc_variant gsc_v_100_variant = { .local_sc_down = 2, }; +static struct gsc_variant gsc_v_5250_variant = { + .pix_max = &gsc_v_5250_max, + .pix_min = &gsc_v_100_min, + .pix_align = &gsc_v_100_align, + .in_buf_cnt = 32, + .out_buf_cnt = 32, + .sc_up_max = 8, + .sc_down_max = 16, + .poly_sc_down_max = 4, + .pre_sc_down_max = 4, + .local_sc_down = 2, +}; + +static struct gsc_variant gsc_v_5420_variant = { + .pix_max = &gsc_v_5420_max, + .pix_min = &gsc_v_100_min, + .pix_align = &gsc_v_100_align, + .in_buf_cnt = 32, + .out_buf_cnt = 32, + .sc_up_max = 8, + .sc_down_max = 16, + .poly_sc_down_max = 4, + .pre_sc_down_max = 4, + .local_sc_down = 2, +}; + +static struct gsc_variant gsc_v_5433_variant = { + .pix_max = &gsc_v_5433_max, + .pix_min = &gsc_v_100_min, + .pix_align = &gsc_v_100_align, + .in_buf_cnt = 32, + .out_buf_cnt = 32, + .sc_up_max = 8, + .sc_down_max = 16, + .poly_sc_down_max = 4, + .pre_sc_down_max = 4, + .local_sc_down = 2, +}; + static struct gsc_driverdata gsc_v_100_drvdata = { .variant = { [0] = &gsc_v_100_variant, @@ -1004,11 +1088,33 @@ static struct gsc_driverdata gsc_v_100_drvdata = { .num_clocks = 1, }; +static struct gsc_driverdata gsc_v_5250_drvdata = { + .variant = { + [0] = &gsc_v_5250_variant, + [1] = &gsc_v_5250_variant, + [2] = &gsc_v_5250_variant, + [3] = &gsc_v_5250_variant, + }, + .num_entities = 4, + .clk_names = { "gscl" }, + .num_clocks = 1, +}; + +static struct gsc_driverdata gsc_v_5420_drvdata = { + .variant = { + [0] = &gsc_v_5420_variant, + [1] = &gsc_v_5420_variant, + }, + .num_entities = 2, + .clk_names = { "gscl" }, + .num_clocks = 1, +}; + static struct gsc_driverdata gsc_5433_drvdata = { .variant = { - [0] = &gsc_v_100_variant, - [1] = &gsc_v_100_variant, - [2] = &gsc_v_100_variant, + [0] = &gsc_v_5433_variant, + [1] = &gsc_v_5433_variant, + [2] = &gsc_v_5433_variant, }, .num_entities = 3, .clk_names = { "pclk", "aclk", "aclk_xiu", "aclk_gsclbend" }, @@ -1017,13 +1123,21 @@ static struct gsc_driverdata gsc_5433_drvdata = { static const struct of_device_id exynos_gsc_match[] = { { - .compatible = "samsung,exynos5-gsc", - .data = &gsc_v_100_drvdata, + .compatible = "samsung,exynos5250-gsc", + .data = &gsc_v_5250_drvdata, + }, + { + .compatible = "samsung,exynos5420-gsc", + .data = &gsc_v_5420_drvdata, }, { .compatible = "samsung,exynos5433-gsc", .data = &gsc_5433_drvdata, }, + { + .compatible = "samsung,exynos5-gsc", + .data = &gsc_v_100_drvdata, + }, {}, }; MODULE_DEVICE_TABLE(of, exynos_gsc_match); @@ -1045,6 +1159,9 @@ static int gsc_probe(struct platform_device *pdev) if (ret < 0) return ret; + if (drv_data == &gsc_v_100_drvdata) + dev_info(dev, "compatible 'exynos5-gsc' is deprecated\n"); + gsc->id = ret; if (gsc->id >= drv_data->num_entities) { dev_err(dev, "Invalid platform device id: %d\n", gsc->id); diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig index c480efb755f5..46a7d242a1a5 100644 --- a/drivers/media/platform/exynos4-is/Kconfig +++ b/drivers/media/platform/exynos4-is/Kconfig @@ -76,7 +76,7 @@ config VIDEO_EXYNOS4_ISP_DMA_CAPTURE depends on VIDEO_EXYNOS4_FIMC_IS select VIDEO_EXYNOS4_IS_COMMON default y - help + help This option enables an additional video device node exposing a V4L2 video capture interface for the FIMC-IS ISP raw (Bayer) capture DMA. diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 948fe01f6c96..ed9302caa004 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -146,6 +146,7 @@ static int fimc_stop_capture(struct fimc_dev *fimc, bool suspend) /** * fimc_capture_config_update - apply the camera interface configuration + * @ctx: FIMC capture context * * To be called from within the interrupt handler with fimc.slock * spinlock held. It updates the camera pixel crop, rotation and @@ -858,6 +859,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, * fimc_get_sensor_frame_desc - query the sensor for media bus frame parameters * @sensor: pointer to the sensor subdev * @plane_fmt: provides plane sizes corresponding to the frame layout entries + * @num_planes: number of planes * @try: true to set the frame parameters, false to query only * * This function is used by this driver only for compressed/blob data formats. @@ -1101,6 +1103,7 @@ static int fimc_cap_g_input(struct file *file, void *priv, unsigned int *i) /** * fimc_pipeline_validate - check for formats inconsistencies * between source and sink pad of each link + * @fimc: the FIMC device this context applies to * * Return 0 if all formats match or -EPIPE otherwise. */ diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index d4656d5175d7..0ef583cfc424 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -60,6 +60,7 @@ static void __setup_sensor_notification(struct fimc_md *fmd, /** * fimc_pipeline_prepare - update pipeline information with subdevice pointers + * @p: fimc pipeline * @me: media entity terminating the pipeline * * Caller holds the graph mutex. @@ -151,8 +152,8 @@ static int __subdev_set_power(struct v4l2_subdev *sd, int on) /** * fimc_pipeline_s_power - change power state of all pipeline subdevs - * @fimc: fimc device terminating the pipeline - * @state: true to power on, false to power off + * @p: fimc device terminating the pipeline + * @on: true to power on, false to power off * * Needs to be called with the graph mutex held. */ @@ -219,6 +220,7 @@ static int __fimc_pipeline_enable(struct exynos_media_pipeline *ep, /** * __fimc_pipeline_open - update the pipeline information, enable power * of all pipeline subdevs and the sensor clock + * @ep: fimc device terminating the pipeline * @me: media entity to start graph walk with * @prepare: true to walk the current pipeline and acquire all subdevs * @@ -252,7 +254,7 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep, /** * __fimc_pipeline_close - disable the sensor clock and pipeline power - * @fimc: fimc device terminating the pipeline + * @ep: fimc device terminating the pipeline * * Disable power of all subdevs and turn the external sensor clock off. */ @@ -281,7 +283,7 @@ static int __fimc_pipeline_close(struct exynos_media_pipeline *ep) /** * __fimc_pipeline_s_stream - call s_stream() on pipeline subdevs - * @pipeline: video pipeline structure + * @ep: video pipeline structure * @on: passed as the s_stream() callback argument */ static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on) @@ -902,6 +904,7 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd) /** * fimc_md_create_links - create default links between registered entities + * @fmd: fimc media device * * Parallel interface sensor entities are connected directly to FIMC capture * entities. The sensors using MIPI CSIS bus are connected through immutable @@ -1405,6 +1408,11 @@ unlock: return media_device_register(&fmd->media_dev); } +static const struct v4l2_async_notifier_operations subdev_notifier_ops = { + .bound = subdev_notifier_bound, + .complete = subdev_notifier_complete, +}; + static int fimc_md_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1479,8 +1487,7 @@ static int fimc_md_probe(struct platform_device *pdev) if (fmd->num_sensors > 0) { fmd->subdev_notifier.subdevs = fmd->async_subdevs; fmd->subdev_notifier.num_subdevs = fmd->num_sensors; - fmd->subdev_notifier.bound = subdev_notifier_bound; - fmd->subdev_notifier.complete = subdev_notifier_complete; + fmd->subdev_notifier.ops = &subdev_notifier_ops; fmd->num_sensors = 0; ret = v4l2_async_notifier_register(&fmd->v4l2_dev, diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index 560aadabcb11..cba46a656338 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -189,7 +189,7 @@ struct csis_drvdata { * @irq: requested s5p-mipi-csis irq number * @interrupt_mask: interrupt mask of the all used interrupts * @flags: the state variable for power and streaming control - * @clock_frequency: device bus clock frequency + * @clk_frequency: device bus clock frequency * @hs_settle: HS-RX settle time * @num_lanes: number of MIPI-CSI data lanes used * @max_num_lanes: maximum number of MIPI-CSI data lanes supported diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index fb43025df573..dba21215dc84 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -339,9 +339,9 @@ static int restart_video_queue(struct viu_dmaqueue *vidq) } } -static void viu_vid_timeout(unsigned long data) +static void viu_vid_timeout(struct timer_list *t) { - struct viu_dev *dev = (struct viu_dev *)data; + struct viu_dev *dev = from_timer(dev, t, vidq.timeout); struct viu_buf *buf; struct viu_dmaqueue *vidq = &dev->vidq; @@ -1466,8 +1466,7 @@ static int viu_of_probe(struct platform_device *op) viu_dev->decoder = v4l2_i2c_new_subdev(&viu_dev->v4l2_dev, ad, "saa7113", VIU_VIDEO_DECODER_ADDR, NULL); - setup_timer(&viu_dev->vidq.timeout, viu_vid_timeout, - (unsigned long)viu_dev); + timer_setup(&viu_dev->vidq.timeout, viu_vid_timeout, 0); viu_dev->std = V4L2_STD_NTSC_M; viu_dev->first = 1; diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c index b7731b18ecae..aa3ce41898bc 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c @@ -59,6 +59,7 @@ struct h264_fb { * @read_idx : read index * @write_idx : write index * @count : buffer count in list + * @reserved : for 8 bytes alignment */ struct h264_ring_fb_list { struct h264_fb fb_list[H264_MAX_FB_NUM]; diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c index b9fad6a48879..3e84a761db3a 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c @@ -155,7 +155,6 @@ struct vdec_vp8_vpu_inst { * @reg_base : HW register base address * @frm_cnt : decode frame count * @ctx : V4L2 context - * @dev : platform device * @vpu : VPU instance for decoder * @vsi : VPU share information */ diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c index 4eb3be37ba14..6cf31b366aad 100644 --- a/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c +++ b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c @@ -34,7 +34,7 @@ static const char h264_filler_marker[] = {0x0, 0x0, 0x0, 0x1, 0xc}; #define H264_FILLER_MARKER_SIZE ARRAY_SIZE(h264_filler_marker) #define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098 -/** +/* * enum venc_h264_vpu_work_buf - h264 encoder buffer index */ enum venc_h264_vpu_work_buf { @@ -50,7 +50,7 @@ enum venc_h264_vpu_work_buf { VENC_H264_VPU_WORK_BUF_MAX, }; -/** +/* * enum venc_h264_bs_mode - for bs_mode argument in h264_enc_vpu_encode */ enum venc_h264_bs_mode { diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c index acb639c4abd2..957420dd60de 100644 --- a/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c +++ b/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c @@ -34,7 +34,7 @@ /* This ac_tag is vp8 frame tag. */ #define MAX_AC_TAG_SIZE 10 -/** +/* * enum venc_vp8_vpu_work_buf - vp8 encoder buffer index */ enum venc_vp8_vpu_work_buf { diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c index 853d598937f6..1ff6a93262b7 100644 --- a/drivers/media/platform/mtk-vpu/mtk_vpu.c +++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c @@ -181,6 +181,7 @@ struct share_obj { * @extmem: VPU extended memory information * @reg: VPU TCM and configuration registers * @run: VPU initialization status + * @wdt: VPU watchdog workqueue * @ipi_desc: VPU IPI descriptor * @recv_buf: VPU DTCM share buffer for receiving. The * receive buffer is only accessed in interrupt context. @@ -194,7 +195,7 @@ struct share_obj { * suppose a client is using VPU to decode VP8. * If the other client wants to encode VP8, * it has to wait until VP8 decode completes. - * @wdt_refcnt WDT reference count to make sure the watchdog can be + * @wdt_refcnt: WDT reference count to make sure the watchdog can be * disabled if no other client is using VPU service * @ack_wq: The wait queue for each codec and mdp. When sleeping * processes wake up, they will check the condition diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 4d29860d27b4..6f1b0c799e58 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -1004,11 +1004,12 @@ static int omap_vout_open(struct file *file) struct omap_vout_device *vout = NULL; vout = video_drvdata(file); - v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__); if (vout == NULL) return -ENODEV; + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__); + /* for now, we only support single open */ if (vout->opened) return -EBUSY; diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 1a428fe9f070..b7ff3842afc0 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -1669,8 +1669,8 @@ static int isp_link_entity( break; } if (i == entity->num_pads) { - dev_err(isp->dev, "%s: no source pad in external entity\n", - __func__); + dev_err(isp->dev, "%s: no source pad in external entity %s\n", + __func__, entity->name); return -EINVAL; } @@ -2001,6 +2001,7 @@ static int isp_remove(struct platform_device *pdev) __omap3isp_put(isp, false); media_entity_enum_cleanup(&isp->crashed); + v4l2_async_notifier_cleanup(&isp->notifier); return 0; } @@ -2011,44 +2012,41 @@ enum isp_of_phy { ISP_OF_PHY_CSIPHY2, }; -static int isp_fwnode_parse(struct device *dev, struct fwnode_handle *fwnode, - struct isp_async_subdev *isd) +static int isp_fwnode_parse(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd) { + struct isp_async_subdev *isd = + container_of(asd, struct isp_async_subdev, asd); struct isp_bus_cfg *buscfg = &isd->bus; - struct v4l2_fwnode_endpoint vep; - unsigned int i; - int ret; bool csi1 = false; - - ret = v4l2_fwnode_endpoint_parse(fwnode, &vep); - if (ret) - return ret; + unsigned int i; dev_dbg(dev, "parsing endpoint %pOF, interface %u\n", - to_of_node(fwnode), vep.base.port); + to_of_node(vep->base.local_fwnode), vep->base.port); - switch (vep.base.port) { + switch (vep->base.port) { case ISP_OF_PHY_PARALLEL: buscfg->interface = ISP_INTERFACE_PARALLEL; buscfg->bus.parallel.data_lane_shift = - vep.bus.parallel.data_shift; + vep->bus.parallel.data_shift; buscfg->bus.parallel.clk_pol = - !!(vep.bus.parallel.flags + !!(vep->bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING); buscfg->bus.parallel.hs_pol = - !!(vep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW); + !!(vep->bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW); buscfg->bus.parallel.vs_pol = - !!(vep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW); + !!(vep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW); buscfg->bus.parallel.fld_pol = - !!(vep.bus.parallel.flags & V4L2_MBUS_FIELD_EVEN_LOW); + !!(vep->bus.parallel.flags & V4L2_MBUS_FIELD_EVEN_LOW); buscfg->bus.parallel.data_pol = - !!(vep.bus.parallel.flags & V4L2_MBUS_DATA_ACTIVE_LOW); - buscfg->bus.parallel.bt656 = vep.bus_type == V4L2_MBUS_BT656; + !!(vep->bus.parallel.flags & V4L2_MBUS_DATA_ACTIVE_LOW); + buscfg->bus.parallel.bt656 = vep->bus_type == V4L2_MBUS_BT656; break; case ISP_OF_PHY_CSIPHY1: case ISP_OF_PHY_CSIPHY2: - switch (vep.bus_type) { + switch (vep->bus_type) { case V4L2_MBUS_CCP2: case V4L2_MBUS_CSI1: dev_dbg(dev, "CSI-1/CCP-2 configuration\n"); @@ -2060,11 +2058,11 @@ static int isp_fwnode_parse(struct device *dev, struct fwnode_handle *fwnode, break; default: dev_err(dev, "unsupported bus type %u\n", - vep.bus_type); + vep->bus_type); return -EINVAL; } - switch (vep.base.port) { + switch (vep->base.port) { case ISP_OF_PHY_CSIPHY1: if (csi1) buscfg->interface = ISP_INTERFACE_CCP2B_PHY1; @@ -2080,47 +2078,47 @@ static int isp_fwnode_parse(struct device *dev, struct fwnode_handle *fwnode, } if (csi1) { buscfg->bus.ccp2.lanecfg.clk.pos = - vep.bus.mipi_csi1.clock_lane; + vep->bus.mipi_csi1.clock_lane; buscfg->bus.ccp2.lanecfg.clk.pol = - vep.bus.mipi_csi1.lane_polarity[0]; + vep->bus.mipi_csi1.lane_polarity[0]; dev_dbg(dev, "clock lane polarity %u, pos %u\n", buscfg->bus.ccp2.lanecfg.clk.pol, buscfg->bus.ccp2.lanecfg.clk.pos); buscfg->bus.ccp2.lanecfg.data[0].pos = - vep.bus.mipi_csi1.data_lane; + vep->bus.mipi_csi1.data_lane; buscfg->bus.ccp2.lanecfg.data[0].pol = - vep.bus.mipi_csi1.lane_polarity[1]; + vep->bus.mipi_csi1.lane_polarity[1]; dev_dbg(dev, "data lane polarity %u, pos %u\n", buscfg->bus.ccp2.lanecfg.data[0].pol, buscfg->bus.ccp2.lanecfg.data[0].pos); buscfg->bus.ccp2.strobe_clk_pol = - vep.bus.mipi_csi1.clock_inv; - buscfg->bus.ccp2.phy_layer = vep.bus.mipi_csi1.strobe; + vep->bus.mipi_csi1.clock_inv; + buscfg->bus.ccp2.phy_layer = vep->bus.mipi_csi1.strobe; buscfg->bus.ccp2.ccp2_mode = - vep.bus_type == V4L2_MBUS_CCP2; + vep->bus_type == V4L2_MBUS_CCP2; buscfg->bus.ccp2.vp_clk_pol = 1; buscfg->bus.ccp2.crc = 1; } else { buscfg->bus.csi2.lanecfg.clk.pos = - vep.bus.mipi_csi2.clock_lane; + vep->bus.mipi_csi2.clock_lane; buscfg->bus.csi2.lanecfg.clk.pol = - vep.bus.mipi_csi2.lane_polarities[0]; + vep->bus.mipi_csi2.lane_polarities[0]; dev_dbg(dev, "clock lane polarity %u, pos %u\n", buscfg->bus.csi2.lanecfg.clk.pol, buscfg->bus.csi2.lanecfg.clk.pos); buscfg->bus.csi2.num_data_lanes = - vep.bus.mipi_csi2.num_data_lanes; + vep->bus.mipi_csi2.num_data_lanes; for (i = 0; i < buscfg->bus.csi2.num_data_lanes; i++) { buscfg->bus.csi2.lanecfg.data[i].pos = - vep.bus.mipi_csi2.data_lanes[i]; + vep->bus.mipi_csi2.data_lanes[i]; buscfg->bus.csi2.lanecfg.data[i].pol = - vep.bus.mipi_csi2.lane_polarities[i + 1]; + vep->bus.mipi_csi2.lane_polarities[i + 1]; dev_dbg(dev, "data lane %u polarity %u, pos %u\n", i, buscfg->bus.csi2.lanecfg.data[i].pol, @@ -2137,57 +2135,13 @@ static int isp_fwnode_parse(struct device *dev, struct fwnode_handle *fwnode, default: dev_warn(dev, "%pOF: invalid interface %u\n", - to_of_node(fwnode), vep.base.port); + to_of_node(vep->base.local_fwnode), vep->base.port); return -EINVAL; } return 0; } -static int isp_fwnodes_parse(struct device *dev, - struct v4l2_async_notifier *notifier) -{ - struct fwnode_handle *fwnode = NULL; - - notifier->subdevs = devm_kcalloc( - dev, ISP_MAX_SUBDEVS, sizeof(*notifier->subdevs), GFP_KERNEL); - if (!notifier->subdevs) - return -ENOMEM; - - while (notifier->num_subdevs < ISP_MAX_SUBDEVS && - (fwnode = fwnode_graph_get_next_endpoint( - of_fwnode_handle(dev->of_node), fwnode))) { - struct isp_async_subdev *isd; - - isd = devm_kzalloc(dev, sizeof(*isd), GFP_KERNEL); - if (!isd) - goto error; - - if (isp_fwnode_parse(dev, fwnode, isd)) { - devm_kfree(dev, isd); - continue; - } - - notifier->subdevs[notifier->num_subdevs] = &isd->asd; - - isd->asd.match.fwnode.fwnode = - fwnode_graph_get_remote_port_parent(fwnode); - if (!isd->asd.match.fwnode.fwnode) { - dev_warn(dev, "bad remote port parent\n"); - goto error; - } - - isd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; - notifier->num_subdevs++; - } - - return notifier->num_subdevs; - -error: - fwnode_handle_put(fwnode); - return -EINVAL; -} - static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async) { struct isp_device *isp = container_of(async, struct isp_device, @@ -2201,7 +2155,7 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async) return ret; list_for_each_entry(sd, &v4l2_dev->subdevs, list) { - if (!sd->asd) + if (sd->notifier != &isp->notifier) continue; ret = isp_link_entity(isp, &sd->entity, @@ -2217,6 +2171,10 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async) return media_device_register(&isp->media_dev); } +static const struct v4l2_async_notifier_operations isp_subdev_notifier_ops = { + .complete = isp_subdev_notifier_complete, +}; + /* * isp_probe - Probe ISP platform device * @pdev: Pointer to ISP platform device @@ -2256,15 +2214,17 @@ static int isp_probe(struct platform_device *pdev) if (ret) return ret; - ret = isp_fwnodes_parse(&pdev->dev, &isp->notifier); - if (ret < 0) - return ret; - isp->autoidle = autoidle; mutex_init(&isp->isp_mutex); spin_lock_init(&isp->stat_lock); + ret = v4l2_async_notifier_parse_fwnode_endpoints( + &pdev->dev, &isp->notifier, sizeof(struct isp_async_subdev), + isp_fwnode_parse); + if (ret < 0) + goto error; + isp->dev = &pdev->dev; isp->ref_count = 0; @@ -2385,7 +2345,7 @@ static int isp_probe(struct platform_device *pdev) if (ret < 0) goto error_register_entities; - isp->notifier.complete = isp_subdev_notifier_complete; + isp->notifier.ops = &isp_subdev_notifier_ops; ret = v4l2_async_notifier_register(&isp->v4l2_dev, &isp->notifier); if (ret) @@ -2406,6 +2366,7 @@ error_isp: isp_xclk_cleanup(isp); __omap3isp_put(isp, false); error: + v4l2_async_notifier_cleanup(&isp->notifier); mutex_destroy(&isp->isp_mutex); return ret; diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index e528df6efc09..8b9043db94b3 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h @@ -220,14 +220,11 @@ struct isp_device { unsigned int sbl_resources; unsigned int subclk_resources; - -#define ISP_MAX_SUBDEVS 8 - struct v4l2_subdev *subdevs[ISP_MAX_SUBDEVS]; }; struct isp_async_subdev { - struct isp_bus_cfg bus; struct v4l2_async_subdev asd; + struct isp_bus_cfg bus; }; #define v4l2_subdev_to_bus_cfg(sd) \ diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c index edca993c2b1f..295f34ad1080 100644 --- a/drivers/media/platform/pxa_camera.c +++ b/drivers/media/platform/pxa_camera.c @@ -235,6 +235,7 @@ enum pxa_mbus_layout { * stored in memory in the following way: * @packing: Type of sample-packing, that has to be used * @order: Sample order when storing in memory + * @layout: Planes layout in memory * @bits_per_sample: How many bits the bridge has to sample */ struct pxa_mbus_pixelfmt { @@ -852,10 +853,10 @@ static void pxa_camera_dma_irq_v(void *data) /** * pxa_init_dma_channel - init dma descriptors * @pcdev: pxa camera device - * @vb: videobuffer2 buffer - * @dma: dma video buffer + * @buf: pxa camera buffer * @channel: dma channel (0 => 'Y', 1 => 'U', 2 => 'V') - * @cibr: camera Receive Buffer Register + * @sg: dma scatter list + * @sglen: dma scatter list length * * Prepares the pxa dma descriptors to transfer one camera channel. * @@ -1010,6 +1011,8 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, /** * pxa_camera_check_link_miss - check missed DMA linking * @pcdev: camera device + * @last_submitted: an opaque DMA cookie for last submitted + * @last_issued: an opaque DMA cookie for last issued * * The DMA chaining is done with DMA running. This means a tiny temporal window * remains, where a buffer is queued on the chain, while the chain is already @@ -2221,6 +2224,11 @@ static void pxa_camera_sensor_unbind(struct v4l2_async_notifier *notifier, mutex_unlock(&pcdev->mlock); } +static const struct v4l2_async_notifier_operations pxa_camera_sensor_ops = { + .bound = pxa_camera_sensor_bound, + .unbind = pxa_camera_sensor_unbind, +}; + /* * Driver probe, remove, suspend and resume operations */ @@ -2489,8 +2497,7 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->asds[0] = &pcdev->asd; pcdev->notifier.subdevs = pcdev->asds; pcdev->notifier.num_subdevs = 1; - pcdev->notifier.bound = pxa_camera_sensor_bound; - pcdev->notifier.unbind = pxa_camera_sensor_unbind; + pcdev->notifier.ops = &pxa_camera_sensor_ops; if (!of_have_populated_dt()) pcdev->asd.match_type = V4L2_ASYNC_MATCH_I2C; diff --git a/drivers/media/platform/qcom/camss-8x16/camss-vfe.c b/drivers/media/platform/qcom/camss-8x16/camss-vfe.c index b22d2dfcd3c2..55232a912950 100644 --- a/drivers/media/platform/qcom/camss-8x16/camss-vfe.c +++ b/drivers/media/platform/qcom/camss-8x16/camss-vfe.c @@ -622,6 +622,9 @@ static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output, reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN; if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16) reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA; + } else { + /* On current devices output->wm_num is always <= 2 */ + break; } if (output->wm_idx[i] % 2 == 1) diff --git a/drivers/media/platform/qcom/camss-8x16/camss-video.c b/drivers/media/platform/qcom/camss-8x16/camss-video.c index cf4219e871bd..ffaa2849e0c1 100644 --- a/drivers/media/platform/qcom/camss-8x16/camss-video.c +++ b/drivers/media/platform/qcom/camss-8x16/camss-video.c @@ -21,7 +21,6 @@ #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-mc.h> -#include <media/videobuf-core.h> #include <media/videobuf2-dma-sg.h> #include "camss-video.h" diff --git a/drivers/media/platform/qcom/camss-8x16/camss.c b/drivers/media/platform/qcom/camss-8x16/camss.c index a3760b5dd1d1..390a42c17b66 100644 --- a/drivers/media/platform/qcom/camss-8x16/camss.c +++ b/drivers/media/platform/qcom/camss-8x16/camss.c @@ -601,6 +601,11 @@ static int camss_subdev_notifier_complete(struct v4l2_async_notifier *async) return media_device_register(&camss->media_dev); } +static const struct v4l2_async_notifier_operations camss_subdev_notifier_ops = { + .bound = camss_subdev_notifier_bound, + .complete = camss_subdev_notifier_complete, +}; + static const struct media_device_ops camss_media_ops = { .link_notify = v4l2_pipeline_link_notify, }; @@ -655,8 +660,7 @@ static int camss_probe(struct platform_device *pdev) goto err_register_entities; if (camss->notifier.num_subdevs) { - camss->notifier.bound = camss_subdev_notifier_bound; - camss->notifier.complete = camss_subdev_notifier_complete; + camss->notifier.ops = &camss_subdev_notifier_ops; ret = v4l2_async_notifier_register(&camss->v4l2_dev, &camss->notifier); diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index cba092bcb76d..a0fe80df0cbd 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -194,7 +194,6 @@ struct venus_buffer { * @fh: a holder of v4l file handle structure * @streamon_cap: stream on flag for capture queue * @streamon_out: stream on flag for output queue - * @cmd_stop: a flag to signal encoder/decoder commands * @width: current capture width * @height: current capture height * @out_width: current output width @@ -258,7 +257,6 @@ struct venus_inst { } controls; struct v4l2_fh fh; unsigned int streamon_cap, streamon_out; - bool cmd_stop; u32 width; u32 height; u32 out_width; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 9b2a401a4891..0ce9559a2924 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -623,13 +623,6 @@ void venus_helper_vb2_buf_queue(struct vb2_buffer *vb) mutex_lock(&inst->lock); - if (inst->cmd_stop) { - vbuf->flags |= V4L2_BUF_FLAG_LAST; - v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); - inst->cmd_stop = false; - goto unlock; - } - v4l2_m2m_buf_queue(m2m_ctx, vbuf); if (!(inst->streamon_out & inst->streamon_cap)) diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index c09490876516..1baf78d3c02d 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -88,12 +88,6 @@ unlock: return ret; } -static int core_deinit_wait_atomic_t(atomic_t *p) -{ - schedule(); - return 0; -} - int hfi_core_deinit(struct venus_core *core, bool blocking) { int ret = 0, empty; @@ -112,7 +106,7 @@ int hfi_core_deinit(struct venus_core *core, bool blocking) if (!empty) { mutex_unlock(&core->lock); - wait_on_atomic_t(&core->insts_count, core_deinit_wait_atomic_t, + wait_on_atomic_t(&core->insts_count, atomic_t_wait, TASK_UNINTERRUPTIBLE); mutex_lock(&core->lock); } @@ -484,6 +478,7 @@ int hfi_session_process_buf(struct venus_inst *inst, struct hfi_frame_data *fd) return -EINVAL; } +EXPORT_SYMBOL_GPL(hfi_session_process_buf); irqreturn_t hfi_isr_thread(int irq, void *dev_id) { diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 1caae8feaa36..734ce11b0ed0 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -344,7 +344,7 @@ static int venus_alloc(struct venus_hfi_device *hdev, struct mem_desc *desc, desc->attrs = DMA_ATTR_WRITE_COMBINE; desc->size = ALIGN(size, SZ_4K); - desc->kva = dma_alloc_attrs(dev, size, &desc->da, GFP_KERNEL, + desc->kva = dma_alloc_attrs(dev, desc->size, &desc->da, GFP_KERNEL, desc->attrs); if (!desc->kva) return -ENOMEM; @@ -710,10 +710,8 @@ static int venus_interface_queues_init(struct venus_hfi_device *hdev) if (ret) return ret; - hdev->ifaceq_table.kva = desc.kva; - hdev->ifaceq_table.da = desc.da; - hdev->ifaceq_table.size = IFACEQ_TABLE_SIZE; - offset = hdev->ifaceq_table.size; + hdev->ifaceq_table = desc; + offset = IFACEQ_TABLE_SIZE; for (i = 0; i < IFACEQ_NUM; i++) { queue = &hdev->queues[i]; @@ -755,9 +753,7 @@ static int venus_interface_queues_init(struct venus_hfi_device *hdev) if (ret) { hdev->sfr.da = 0; } else { - hdev->sfr.da = desc.da; - hdev->sfr.kva = desc.kva; - hdev->sfr.size = ALIGNED_SFR_SIZE; + hdev->sfr = desc; sfr = hdev->sfr.kva; sfr->buf_size = ALIGNED_SFR_SIZE; } diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index da611a5eb670..c9e9576bb08a 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -469,8 +469,14 @@ static int vdec_subscribe_event(struct v4l2_fh *fh, static int vdec_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) { - if (cmd->cmd != V4L2_DEC_CMD_STOP) + switch (cmd->cmd) { + case V4L2_DEC_CMD_STOP: + if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK) + return -EINVAL; + break; + default: return -EINVAL; + } return 0; } @@ -479,6 +485,7 @@ static int vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) { struct venus_inst *inst = to_inst(file); + struct hfi_frame_data fdata = {0}; int ret; ret = vdec_try_decoder_cmd(file, fh, cmd); @@ -486,12 +493,23 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) return ret; mutex_lock(&inst->lock); - inst->cmd_stop = true; - mutex_unlock(&inst->lock); - hfi_session_flush(inst); + /* + * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on decoder + * input to signal EOS. + */ + if (!(inst->streamon_out & inst->streamon_cap)) + goto unlock; + + fdata.buffer_type = HFI_BUFFER_INPUT; + fdata.flags |= HFI_BUFFERFLAG_EOS; + fdata.device_addr = 0xdeadbeef; - return 0; + ret = hfi_session_process_buf(inst, &fdata); + +unlock: + mutex_unlock(&inst->lock); + return ret; } static const struct v4l2_ioctl_ops vdec_ioctl_ops = { @@ -718,7 +736,6 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) inst->reconfig = false; inst->sequence_cap = 0; inst->sequence_out = 0; - inst->cmd_stop = false; ret = vdec_init_session(inst); if (ret) @@ -807,11 +824,6 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type, vb->timestamp = timestamp_us * NSEC_PER_USEC; vbuf->sequence = inst->sequence_cap++; - if (inst->cmd_stop) { - vbuf->flags |= V4L2_BUF_FLAG_LAST; - inst->cmd_stop = false; - } - if (vbuf->flags & V4L2_BUF_FLAG_LAST) { const struct v4l2_event ev = { .type = V4L2_EVENT_EOS }; diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 6f123a387cf9..3fcf0e9b7b29 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -963,13 +963,12 @@ static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type, if (!vbuf) return; - vb = &vbuf->vb2_buf; - vb->planes[0].bytesused = bytesused; - vb->planes[0].data_offset = data_offset; - vbuf->flags = flags; if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + vb = &vbuf->vb2_buf; + vb2_set_plane_payload(vb, 0, bytesused + data_offset); + vb->planes[0].data_offset = data_offset; vb->timestamp = timestamp_us * NSEC_PER_USEC; vbuf->sequence = inst->sequence_cap++; } else { diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 142de447aaaa..108d776f3265 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -21,6 +21,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <media/v4l2-async.h> #include <media/v4l2-fwnode.h> #include "rcar-vin.h" @@ -77,14 +78,14 @@ static int rvin_digital_notify_complete(struct v4l2_async_notifier *notifier) int ret; /* Verify subdevices mbus format */ - if (!rvin_mbus_supported(&vin->digital)) { + if (!rvin_mbus_supported(vin->digital)) { vin_err(vin, "Unsupported media bus format for %s\n", - vin->digital.subdev->name); + vin->digital->subdev->name); return -EINVAL; } vin_dbg(vin, "Found media bus format for %s: %d\n", - vin->digital.subdev->name, vin->digital.code); + vin->digital->subdev->name, vin->digital->code); ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev); if (ret < 0) { @@ -103,7 +104,7 @@ static void rvin_digital_notify_unbind(struct v4l2_async_notifier *notifier, vin_dbg(vin, "unbind digital subdev %s\n", subdev->name); rvin_v4l2_remove(vin); - vin->digital.subdev = NULL; + vin->digital->subdev = NULL; } static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier, @@ -120,117 +121,75 @@ static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier, ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SOURCE); if (ret < 0) return ret; - vin->digital.source_pad = ret; + vin->digital->source_pad = ret; ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK); - vin->digital.sink_pad = ret < 0 ? 0 : ret; + vin->digital->sink_pad = ret < 0 ? 0 : ret; - vin->digital.subdev = subdev; + vin->digital->subdev = subdev; vin_dbg(vin, "bound subdev %s source pad: %u sink pad: %u\n", - subdev->name, vin->digital.source_pad, - vin->digital.sink_pad); + subdev->name, vin->digital->source_pad, + vin->digital->sink_pad); return 0; } +static const struct v4l2_async_notifier_operations rvin_digital_notify_ops = { + .bound = rvin_digital_notify_bound, + .unbind = rvin_digital_notify_unbind, + .complete = rvin_digital_notify_complete, +}; + -static int rvin_digitial_parse_v4l2(struct rvin_dev *vin, - struct device_node *ep, - struct v4l2_mbus_config *mbus_cfg) +static int rvin_digital_parse_v4l2(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd) { - struct v4l2_fwnode_endpoint v4l2_ep; - int ret; + struct rvin_dev *vin = dev_get_drvdata(dev); + struct rvin_graph_entity *rvge = + container_of(asd, struct rvin_graph_entity, asd); - ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &v4l2_ep); - if (ret) { - vin_err(vin, "Could not parse v4l2 endpoint\n"); - return -EINVAL; - } + if (vep->base.port || vep->base.id) + return -ENOTCONN; - mbus_cfg->type = v4l2_ep.bus_type; + rvge->mbus_cfg.type = vep->bus_type; - switch (mbus_cfg->type) { + switch (rvge->mbus_cfg.type) { case V4L2_MBUS_PARALLEL: vin_dbg(vin, "Found PARALLEL media bus\n"); - mbus_cfg->flags = v4l2_ep.bus.parallel.flags; + rvge->mbus_cfg.flags = vep->bus.parallel.flags; break; case V4L2_MBUS_BT656: vin_dbg(vin, "Found BT656 media bus\n"); - mbus_cfg->flags = 0; + rvge->mbus_cfg.flags = 0; break; default: vin_err(vin, "Unknown media bus type\n"); return -EINVAL; } - return 0; -} - -static int rvin_digital_graph_parse(struct rvin_dev *vin) -{ - struct device_node *ep, *np; - int ret; - - vin->digital.asd.match.fwnode.fwnode = NULL; - vin->digital.subdev = NULL; - - /* - * Port 0 id 0 is local digital input, try to get it. - * Not all instances can or will have this, that is OK - */ - ep = of_graph_get_endpoint_by_regs(vin->dev->of_node, 0, 0); - if (!ep) - return 0; - - np = of_graph_get_remote_port_parent(ep); - if (!np) { - vin_err(vin, "No remote parent for digital input\n"); - of_node_put(ep); - return -EINVAL; - } - of_node_put(np); - - ret = rvin_digitial_parse_v4l2(vin, ep, &vin->digital.mbus_cfg); - of_node_put(ep); - if (ret) - return ret; - - vin->digital.asd.match.fwnode.fwnode = of_fwnode_handle(np); - vin->digital.asd.match_type = V4L2_ASYNC_MATCH_FWNODE; + vin->digital = rvge; return 0; } static int rvin_digital_graph_init(struct rvin_dev *vin) { - struct v4l2_async_subdev **subdevs = NULL; int ret; - ret = rvin_digital_graph_parse(vin); + ret = v4l2_async_notifier_parse_fwnode_endpoints( + vin->dev, &vin->notifier, + sizeof(struct rvin_graph_entity), rvin_digital_parse_v4l2); if (ret) return ret; - if (!vin->digital.asd.match.fwnode.fwnode) { - vin_dbg(vin, "No digital subdevice found\n"); + if (!vin->digital) return -ENODEV; - } - - /* Register the subdevices notifier. */ - subdevs = devm_kzalloc(vin->dev, sizeof(*subdevs), GFP_KERNEL); - if (subdevs == NULL) - return -ENOMEM; - - subdevs[0] = &vin->digital.asd; vin_dbg(vin, "Found digital subdevice %pOF\n", - to_of_node(subdevs[0]->match.fwnode.fwnode)); - - vin->notifier.num_subdevs = 1; - vin->notifier.subdevs = subdevs; - vin->notifier.bound = rvin_digital_notify_bound; - vin->notifier.unbind = rvin_digital_notify_unbind; - vin->notifier.complete = rvin_digital_notify_complete; + to_of_node(vin->digital->asd.match.fwnode.fwnode)); + vin->notifier.ops = &rvin_digital_notify_ops; ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier); if (ret < 0) { vin_err(vin, "Notifier registration failed\n"); @@ -290,6 +249,8 @@ static int rcar_vin_probe(struct platform_device *pdev) if (ret) return ret; + platform_set_drvdata(pdev, vin); + ret = rvin_digital_graph_init(vin); if (ret < 0) goto error; @@ -297,11 +258,10 @@ static int rcar_vin_probe(struct platform_device *pdev) pm_suspend_ignore_children(&pdev->dev, true); pm_runtime_enable(&pdev->dev); - platform_set_drvdata(pdev, vin); - return 0; error: rvin_dma_remove(vin); + v4l2_async_notifier_cleanup(&vin->notifier); return ret; } @@ -313,6 +273,7 @@ static int rcar_vin_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); v4l2_async_notifier_unregister(&vin->notifier); + v4l2_async_notifier_cleanup(&vin->notifier); rvin_dma_remove(vin); diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index b136844499f6..23fdff7a7370 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -183,7 +183,7 @@ static int rvin_setup(struct rvin_dev *vin) /* * Input interface */ - switch (vin->digital.code) { + switch (vin->digital->code) { case MEDIA_BUS_FMT_YUYV8_1X16: /* BT.601/BT.1358 16bit YCbCr422 */ vnmc |= VNMC_INF_YUV16; @@ -191,7 +191,7 @@ static int rvin_setup(struct rvin_dev *vin) break; case MEDIA_BUS_FMT_UYVY8_2X8: /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */ - vnmc |= vin->digital.mbus_cfg.type == V4L2_MBUS_BT656 ? + vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ? VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601; input_is_yuv = true; break; @@ -200,7 +200,7 @@ static int rvin_setup(struct rvin_dev *vin) break; case MEDIA_BUS_FMT_UYVY10_2X10: /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */ - vnmc |= vin->digital.mbus_cfg.type == V4L2_MBUS_BT656 ? + vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ? VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601; input_is_yuv = true; break; @@ -212,11 +212,11 @@ static int rvin_setup(struct rvin_dev *vin) dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1); /* Hsync Signal Polarity Select */ - if (!(vin->digital.mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) + if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) dmr2 |= VNDMR2_HPS; /* Vsync Signal Polarity Select */ - if (!(vin->digital.mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) + if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) dmr2 |= VNDMR2_VPS; /* diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index dd37ea811680..b479b882da12 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -111,7 +111,7 @@ static int rvin_reset_format(struct rvin_dev *vin) struct v4l2_mbus_framefmt *mf = &fmt.format; int ret; - fmt.pad = vin->digital.source_pad; + fmt.pad = vin->digital->source_pad; ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt); if (ret) @@ -172,13 +172,13 @@ static int __rvin_try_format_source(struct rvin_dev *vin, sd = vin_to_source(vin); - v4l2_fill_mbus_format(&format.format, pix, vin->digital.code); + v4l2_fill_mbus_format(&format.format, pix, vin->digital->code); pad_cfg = v4l2_subdev_alloc_pad_config(sd); if (pad_cfg == NULL) return -ENOMEM; - format.pad = vin->digital.source_pad; + format.pad = vin->digital->source_pad; field = pix->field; @@ -555,7 +555,7 @@ static int rvin_enum_dv_timings(struct file *file, void *priv_fh, if (timings->pad) return -EINVAL; - timings->pad = vin->digital.sink_pad; + timings->pad = vin->digital->sink_pad; ret = v4l2_subdev_call(sd, pad, enum_dv_timings, timings); @@ -607,7 +607,7 @@ static int rvin_dv_timings_cap(struct file *file, void *priv_fh, if (cap->pad) return -EINVAL; - cap->pad = vin->digital.sink_pad; + cap->pad = vin->digital->sink_pad; ret = v4l2_subdev_call(sd, pad, dv_timings_cap, cap); @@ -625,7 +625,7 @@ static int rvin_g_edid(struct file *file, void *fh, struct v4l2_edid *edid) if (edid->pad) return -EINVAL; - edid->pad = vin->digital.sink_pad; + edid->pad = vin->digital->sink_pad; ret = v4l2_subdev_call(sd, pad, get_edid, edid); @@ -643,7 +643,7 @@ static int rvin_s_edid(struct file *file, void *fh, struct v4l2_edid *edid) if (edid->pad) return -EINVAL; - edid->pad = vin->digital.sink_pad; + edid->pad = vin->digital->sink_pad; ret = v4l2_subdev_call(sd, pad, set_edid, edid); diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h index 9bfb5a7c4dc4..5382078143fb 100644 --- a/drivers/media/platform/rcar-vin/rcar-vin.h +++ b/drivers/media/platform/rcar-vin/rcar-vin.h @@ -126,7 +126,7 @@ struct rvin_dev { struct v4l2_device v4l2_dev; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_async_notifier notifier; - struct rvin_graph_entity digital; + struct rvin_graph_entity *digital; struct mutex lock; struct vb2_queue queue; @@ -145,7 +145,7 @@ struct rvin_dev { struct v4l2_rect compose; }; -#define vin_to_source(vin) vin->digital.subdev +#define vin_to_source(vin) ((vin)->digital->subdev) /* Debug */ #define vin_dbg(d, fmt, arg...) dev_dbg(d->dev, fmt, ##arg) diff --git a/drivers/media/platform/rcar_drif.c b/drivers/media/platform/rcar_drif.c index 522364ff0d5d..63c94f4028a7 100644 --- a/drivers/media/platform/rcar_drif.c +++ b/drivers/media/platform/rcar_drif.c @@ -630,7 +630,7 @@ static int rcar_drif_enable_rx(struct rcar_drif_sdr *sdr) { unsigned int i; u32 ctr; - int ret; + int ret = -EINVAL; /* * When both internal channels are enabled, they can be synchronized @@ -1185,6 +1185,12 @@ error: return ret; } +static const struct v4l2_async_notifier_operations rcar_drif_notify_ops = { + .bound = rcar_drif_notify_bound, + .unbind = rcar_drif_notify_unbind, + .complete = rcar_drif_notify_complete, +}; + /* Read endpoint properties */ static void rcar_drif_get_ep_properties(struct rcar_drif_sdr *sdr, struct fwnode_handle *fwnode) @@ -1347,9 +1353,7 @@ static int rcar_drif_sdr_probe(struct rcar_drif_sdr *sdr) if (ret) goto error; - sdr->notifier.bound = rcar_drif_notify_bound; - sdr->notifier.unbind = rcar_drif_notify_unbind; - sdr->notifier.complete = rcar_drif_notify_complete; + sdr->notifier.ops = &rcar_drif_notify_ops; /* Register notifier */ ret = v4l2_async_notifier_register(&sdr->v4l2_dev, &sdr->notifier); diff --git a/drivers/media/platform/rcar_fdp1.c b/drivers/media/platform/rcar_fdp1.c index 3245bc45f4a0..b13dec3081e5 100644 --- a/drivers/media/platform/rcar_fdp1.c +++ b/drivers/media/platform/rcar_fdp1.c @@ -1132,7 +1132,7 @@ static int fdp1_device_process(struct fdp1_ctx *ctx) * mem2mem callbacks */ -/** +/* * job_ready() - check whether an instance is ready to be scheduled to run */ static int fdp1_m2m_job_ready(void *priv) diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c index 070bac36d766..f6092ae45912 100644 --- a/drivers/media/platform/rcar_jpu.c +++ b/drivers/media/platform/rcar_jpu.c @@ -257,7 +257,7 @@ struct jpu_fmt { }; /** - * jpu_q_data - parameters of one queue + * struct jpu_q_data - parameters of one queue * @fmtinfo: driver-specific format of this queue * @format: multiplanar format of this queue * @sequence: sequence number @@ -269,7 +269,7 @@ struct jpu_q_data { }; /** - * jpu_ctx - the device context data + * struct jpu_ctx - the device context data * @jpu: JPEG IP device for this context * @encoder: compression (encode) operation or decompression (decode) * @compr_quality: destination image quality in compression (encode) mode diff --git a/drivers/media/platform/rockchip/rga/Makefile b/drivers/media/platform/rockchip/rga/Makefile new file mode 100644 index 000000000000..92fe25490ccd --- /dev/null +++ b/drivers/media/platform/rockchip/rga/Makefile @@ -0,0 +1,3 @@ +rockchip-rga-objs := rga.o rga-hw.o rga-buf.o + +obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip-rga.o diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c new file mode 100644 index 000000000000..49cacc7a48d1 --- /dev/null +++ b/drivers/media/platform/rockchip/rga/rga-buf.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2017 Fuzhou Rockchip Electronics Co.Ltd + * Author: Jacob Chen <jacob-chen@iotwrt.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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/pm_runtime.h> + +#include <media/v4l2-device.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-mem2mem.h> +#include <media/videobuf2-dma-sg.h> +#include <media/videobuf2-v4l2.h> + +#include "rga-hw.h" +#include "rga.h" + +static int +rga_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) +{ + struct rga_ctx *ctx = vb2_get_drv_priv(vq); + struct rga_frame *f = rga_get_frame(ctx, vq->type); + + if (IS_ERR(f)) + return PTR_ERR(f); + + if (*nplanes) + return sizes[0] < f->size ? -EINVAL : 0; + + sizes[0] = f->size; + *nplanes = 1; + + return 0; +} + +static int rga_buf_prepare(struct vb2_buffer *vb) +{ + struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct rga_frame *f = rga_get_frame(ctx, vb->vb2_queue->type); + + if (IS_ERR(f)) + return PTR_ERR(f); + + vb2_set_plane_payload(vb, 0, f->size); + + return 0; +} + +static void rga_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); +} + +static int rga_buf_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct rga_ctx *ctx = vb2_get_drv_priv(q); + struct rockchip_rga *rga = ctx->rga; + int ret, i; + + ret = pm_runtime_get_sync(rga->dev); + + if (!ret) + return 0; + + for (i = 0; i < q->num_buffers; ++i) { + if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) { + v4l2_m2m_buf_done(to_vb2_v4l2_buffer(q->bufs[i]), + VB2_BUF_STATE_QUEUED); + } + } + + return ret; +} + +static void rga_buf_stop_streaming(struct vb2_queue *q) +{ + struct rga_ctx *ctx = vb2_get_drv_priv(q); + struct rockchip_rga *rga = ctx->rga; + struct vb2_v4l2_buffer *vbuf; + + for (;;) { + if (V4L2_TYPE_IS_OUTPUT(q->type)) + vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + else + vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + if (!vbuf) + break; + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); + } + + pm_runtime_put(rga->dev); +} + +const struct vb2_ops rga_qops = { + .queue_setup = rga_queue_setup, + .buf_prepare = rga_buf_prepare, + .buf_queue = rga_buf_queue, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .start_streaming = rga_buf_start_streaming, + .stop_streaming = rga_buf_stop_streaming, +}; + +/* RGA MMU is a 1-Level MMU, so it can't be used through the IOMMU API. + * We use it more like a scatter-gather list. + */ +void rga_buf_map(struct vb2_buffer *vb) +{ + struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct rockchip_rga *rga = ctx->rga; + struct sg_table *sgt; + struct scatterlist *sgl; + unsigned int *pages; + unsigned int address, len, i, p; + unsigned int mapped_size = 0; + + if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + pages = rga->src_mmu_pages; + else + pages = rga->dst_mmu_pages; + + /* Create local MMU table for RGA */ + sgt = vb2_plane_cookie(vb, 0); + + for_each_sg(sgt->sgl, sgl, sgt->nents, i) { + len = sg_dma_len(sgl) >> PAGE_SHIFT; + address = sg_phys(sgl); + + for (p = 0; p < len; p++) { + dma_addr_t phys = address + (p << PAGE_SHIFT); + + pages[mapped_size + p] = phys; + } + + mapped_size += len; + } + + /* sync local MMU table for RGA */ + dma_sync_single_for_device(rga->dev, virt_to_phys(pages), + 8 * PAGE_SIZE, DMA_BIDIRECTIONAL); +} diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c new file mode 100644 index 000000000000..96d1b1b3fe8e --- /dev/null +++ b/drivers/media/platform/rockchip/rga/rga-hw.c @@ -0,0 +1,421 @@ +/* + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd + * Author: Jacob Chen <jacob-chen@iotwrt.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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/pm_runtime.h> + +#include "rga-hw.h" +#include "rga.h" + +enum e_rga_start_pos { + LT = 0, + LB = 1, + RT = 2, + RB = 3, +}; + +struct rga_addr_offset { + unsigned int y_off; + unsigned int u_off; + unsigned int v_off; +}; + +struct rga_corners_addr_offset { + struct rga_addr_offset left_top; + struct rga_addr_offset right_top; + struct rga_addr_offset left_bottom; + struct rga_addr_offset right_bottom; +}; + +static unsigned int rga_get_scaling(unsigned int src, unsigned int dst) +{ + /* + * The rga hw scaling factor is a normalized inverse of the + * scaling factor. + * For example: When source width is 100 and destination width is 200 + * (scaling of 2x), then the hw factor is NC * 100 / 200. + * The normalization factor (NC) is 2^16 = 0x10000. + */ + + return (src > dst) ? ((dst << 16) / src) : ((src << 16) / dst); +} + +static struct rga_corners_addr_offset +rga_get_addr_offset(struct rga_frame *frm, unsigned int x, unsigned int y, + unsigned int w, unsigned int h) +{ + struct rga_corners_addr_offset offsets; + struct rga_addr_offset *lt, *lb, *rt, *rb; + unsigned int x_div = 0, + y_div = 0, uv_stride = 0, pixel_width = 0, uv_factor = 0; + + lt = &offsets.left_top; + lb = &offsets.left_bottom; + rt = &offsets.right_top; + rb = &offsets.right_bottom; + + x_div = frm->fmt->x_div; + y_div = frm->fmt->y_div; + uv_factor = frm->fmt->uv_factor; + uv_stride = frm->stride / x_div; + pixel_width = frm->stride / frm->width; + + lt->y_off = y * frm->stride + x * pixel_width; + lt->u_off = + frm->width * frm->height + (y / y_div) * uv_stride + x / x_div; + lt->v_off = lt->u_off + frm->width * frm->height / uv_factor; + + lb->y_off = lt->y_off + (h - 1) * frm->stride; + lb->u_off = lt->u_off + (h / y_div - 1) * uv_stride; + lb->v_off = lt->v_off + (h / y_div - 1) * uv_stride; + + rt->y_off = lt->y_off + (w - 1) * pixel_width; + rt->u_off = lt->u_off + w / x_div - 1; + rt->v_off = lt->v_off + w / x_div - 1; + + rb->y_off = lb->y_off + (w - 1) * pixel_width; + rb->u_off = lb->u_off + w / x_div - 1; + rb->v_off = lb->v_off + w / x_div - 1; + + return offsets; +} + +static struct rga_addr_offset *rga_lookup_draw_pos(struct + rga_corners_addr_offset + * offsets, u32 rotate_mode, + u32 mirr_mode) +{ + static enum e_rga_start_pos rot_mir_point_matrix[4][4] = { + { + LT, RT, LB, RB, + }, + { + RT, LT, RB, LB, + }, + { + RB, LB, RT, LT, + }, + { + LB, RB, LT, RT, + }, + }; + + if (!offsets) + return NULL; + + switch (rot_mir_point_matrix[rotate_mode][mirr_mode]) { + case LT: + return &offsets->left_top; + case LB: + return &offsets->left_bottom; + case RT: + return &offsets->right_top; + case RB: + return &offsets->right_bottom; + } + + return NULL; +} + +static void rga_cmd_set_src_addr(struct rga_ctx *ctx, void *mmu_pages) +{ + struct rockchip_rga *rga = ctx->rga; + u32 *dest = rga->cmdbuf_virt; + unsigned int reg; + + reg = RGA_MMU_SRC_BASE - RGA_MODE_BASE_REG; + dest[reg >> 2] = virt_to_phys(mmu_pages) >> 4; + + reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG; + dest[reg >> 2] |= 0x7; +} + +static void rga_cmd_set_src1_addr(struct rga_ctx *ctx, void *mmu_pages) +{ + struct rockchip_rga *rga = ctx->rga; + u32 *dest = rga->cmdbuf_virt; + unsigned int reg; + + reg = RGA_MMU_SRC1_BASE - RGA_MODE_BASE_REG; + dest[reg >> 2] = virt_to_phys(mmu_pages) >> 4; + + reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG; + dest[reg >> 2] |= 0x7 << 4; +} + +static void rga_cmd_set_dst_addr(struct rga_ctx *ctx, void *mmu_pages) +{ + struct rockchip_rga *rga = ctx->rga; + u32 *dest = rga->cmdbuf_virt; + unsigned int reg; + + reg = RGA_MMU_DST_BASE - RGA_MODE_BASE_REG; + dest[reg >> 2] = virt_to_phys(mmu_pages) >> 4; + + reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG; + dest[reg >> 2] |= 0x7 << 8; +} + +static void rga_cmd_set_trans_info(struct rga_ctx *ctx) +{ + struct rockchip_rga *rga = ctx->rga; + u32 *dest = rga->cmdbuf_virt; + unsigned int scale_dst_w, scale_dst_h; + unsigned int src_h, src_w, src_x, src_y, dst_h, dst_w, dst_x, dst_y; + union rga_src_info src_info; + union rga_dst_info dst_info; + union rga_src_x_factor x_factor; + union rga_src_y_factor y_factor; + union rga_src_vir_info src_vir_info; + union rga_src_act_info src_act_info; + union rga_dst_vir_info dst_vir_info; + union rga_dst_act_info dst_act_info; + + struct rga_addr_offset *dst_offset; + struct rga_corners_addr_offset offsets; + struct rga_corners_addr_offset src_offsets; + + src_h = ctx->in.crop.height; + src_w = ctx->in.crop.width; + src_x = ctx->in.crop.left; + src_y = ctx->in.crop.top; + dst_h = ctx->out.crop.height; + dst_w = ctx->out.crop.width; + dst_x = ctx->out.crop.left; + dst_y = ctx->out.crop.top; + + src_info.val = dest[(RGA_SRC_INFO - RGA_MODE_BASE_REG) >> 2]; + dst_info.val = dest[(RGA_DST_INFO - RGA_MODE_BASE_REG) >> 2]; + x_factor.val = dest[(RGA_SRC_X_FACTOR - RGA_MODE_BASE_REG) >> 2]; + y_factor.val = dest[(RGA_SRC_Y_FACTOR - RGA_MODE_BASE_REG) >> 2]; + src_vir_info.val = dest[(RGA_SRC_VIR_INFO - RGA_MODE_BASE_REG) >> 2]; + src_act_info.val = dest[(RGA_SRC_ACT_INFO - RGA_MODE_BASE_REG) >> 2]; + dst_vir_info.val = dest[(RGA_DST_VIR_INFO - RGA_MODE_BASE_REG) >> 2]; + dst_act_info.val = dest[(RGA_DST_ACT_INFO - RGA_MODE_BASE_REG) >> 2]; + + src_info.data.format = ctx->in.fmt->hw_format; + src_info.data.swap = ctx->in.fmt->color_swap; + dst_info.data.format = ctx->out.fmt->hw_format; + dst_info.data.swap = ctx->out.fmt->color_swap; + + if (ctx->in.fmt->hw_format >= RGA_COLOR_FMT_YUV422SP) { + if (ctx->out.fmt->hw_format < RGA_COLOR_FMT_YUV422SP) { + switch (ctx->in.colorspace) { + case V4L2_COLORSPACE_REC709: + src_info.data.csc_mode = + RGA_SRC_CSC_MODE_BT709_R0; + break; + default: + src_info.data.csc_mode = + RGA_SRC_CSC_MODE_BT601_R0; + break; + } + } + } + + if (ctx->out.fmt->hw_format >= RGA_COLOR_FMT_YUV422SP) { + switch (ctx->out.colorspace) { + case V4L2_COLORSPACE_REC709: + dst_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0; + break; + default: + dst_info.data.csc_mode = RGA_DST_CSC_MODE_BT601_R0; + break; + } + } + + if (ctx->vflip) + src_info.data.mir_mode |= RGA_SRC_MIRR_MODE_X; + + if (ctx->hflip) + src_info.data.mir_mode |= RGA_SRC_MIRR_MODE_Y; + + switch (ctx->rotate) { + case 90: + src_info.data.rot_mode = RGA_SRC_ROT_MODE_90_DEGREE; + break; + case 180: + src_info.data.rot_mode = RGA_SRC_ROT_MODE_180_DEGREE; + break; + case 270: + src_info.data.rot_mode = RGA_SRC_ROT_MODE_270_DEGREE; + break; + default: + src_info.data.rot_mode = RGA_SRC_ROT_MODE_0_DEGREE; + break; + } + + /* + * Cacluate the up/down scaling mode/factor. + * + * RGA used to scale the picture first, and then rotate second, + * so we need to swap the w/h when rotate degree is 90/270. + */ + if (src_info.data.rot_mode == RGA_SRC_ROT_MODE_90_DEGREE || + src_info.data.rot_mode == RGA_SRC_ROT_MODE_270_DEGREE) { + if (rga->version.major == 0 || rga->version.minor == 0) { + if (dst_w == src_h) + src_h -= 8; + if (abs(src_w - dst_h) < 16) + src_w -= 16; + } + + scale_dst_h = dst_w; + scale_dst_w = dst_h; + } else { + scale_dst_w = dst_w; + scale_dst_h = dst_h; + } + + if (src_w == scale_dst_w) { + src_info.data.hscl_mode = RGA_SRC_HSCL_MODE_NO; + x_factor.val = 0; + } else if (src_w > scale_dst_w) { + src_info.data.hscl_mode = RGA_SRC_HSCL_MODE_DOWN; + x_factor.data.down_scale_factor = + rga_get_scaling(src_w, scale_dst_w) + 1; + } else { + src_info.data.hscl_mode = RGA_SRC_HSCL_MODE_UP; + x_factor.data.up_scale_factor = + rga_get_scaling(src_w - 1, scale_dst_w - 1); + } + + if (src_h == scale_dst_h) { + src_info.data.vscl_mode = RGA_SRC_VSCL_MODE_NO; + y_factor.val = 0; + } else if (src_h > scale_dst_h) { + src_info.data.vscl_mode = RGA_SRC_VSCL_MODE_DOWN; + y_factor.data.down_scale_factor = + rga_get_scaling(src_h, scale_dst_h) + 1; + } else { + src_info.data.vscl_mode = RGA_SRC_VSCL_MODE_UP; + y_factor.data.up_scale_factor = + rga_get_scaling(src_h - 1, scale_dst_h - 1); + } + + /* + * Cacluate the framebuffer virtual strides and active size, + * note that the step of vir_stride / vir_width is 4 byte words + */ + src_vir_info.data.vir_stride = ctx->in.stride >> 2; + src_vir_info.data.vir_width = ctx->in.stride >> 2; + + src_act_info.data.act_height = src_h - 1; + src_act_info.data.act_width = src_w - 1; + + dst_vir_info.data.vir_stride = ctx->out.stride >> 2; + dst_act_info.data.act_height = dst_h - 1; + dst_act_info.data.act_width = dst_w - 1; + + /* + * Cacluate the source framebuffer base address with offset pixel. + */ + src_offsets = rga_get_addr_offset(&ctx->in, src_x, src_y, + src_w, src_h); + + /* + * Configure the dest framebuffer base address with pixel offset. + */ + offsets = rga_get_addr_offset(&ctx->out, dst_x, dst_y, dst_w, dst_h); + dst_offset = rga_lookup_draw_pos(&offsets, src_info.data.rot_mode, + src_info.data.mir_mode); + + dest[(RGA_SRC_Y_RGB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = + src_offsets.left_top.y_off; + dest[(RGA_SRC_CB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = + src_offsets.left_top.u_off; + dest[(RGA_SRC_CR_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = + src_offsets.left_top.v_off; + + dest[(RGA_SRC_X_FACTOR - RGA_MODE_BASE_REG) >> 2] = x_factor.val; + dest[(RGA_SRC_Y_FACTOR - RGA_MODE_BASE_REG) >> 2] = y_factor.val; + dest[(RGA_SRC_VIR_INFO - RGA_MODE_BASE_REG) >> 2] = src_vir_info.val; + dest[(RGA_SRC_ACT_INFO - RGA_MODE_BASE_REG) >> 2] = src_act_info.val; + + dest[(RGA_SRC_INFO - RGA_MODE_BASE_REG) >> 2] = src_info.val; + + dest[(RGA_DST_Y_RGB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = + dst_offset->y_off; + dest[(RGA_DST_CB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = + dst_offset->u_off; + dest[(RGA_DST_CR_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = + dst_offset->v_off; + + dest[(RGA_DST_VIR_INFO - RGA_MODE_BASE_REG) >> 2] = dst_vir_info.val; + dest[(RGA_DST_ACT_INFO - RGA_MODE_BASE_REG) >> 2] = dst_act_info.val; + + dest[(RGA_DST_INFO - RGA_MODE_BASE_REG) >> 2] = dst_info.val; +} + +static void rga_cmd_set_mode(struct rga_ctx *ctx) +{ + struct rockchip_rga *rga = ctx->rga; + u32 *dest = rga->cmdbuf_virt; + union rga_mode_ctrl mode; + union rga_alpha_ctrl0 alpha_ctrl0; + union rga_alpha_ctrl1 alpha_ctrl1; + + mode.val = 0; + alpha_ctrl0.val = 0; + alpha_ctrl1.val = 0; + + mode.data.gradient_sat = 1; + mode.data.render = RGA_MODE_RENDER_BITBLT; + mode.data.bitblt = RGA_MODE_BITBLT_MODE_SRC_TO_DST; + + /* disable alpha blending */ + dest[(RGA_ALPHA_CTRL0 - RGA_MODE_BASE_REG) >> 2] = alpha_ctrl0.val; + dest[(RGA_ALPHA_CTRL1 - RGA_MODE_BASE_REG) >> 2] = alpha_ctrl1.val; + + dest[(RGA_MODE_CTRL - RGA_MODE_BASE_REG) >> 2] = mode.val; +} + +static void rga_cmd_set(struct rga_ctx *ctx) +{ + struct rockchip_rga *rga = ctx->rga; + + memset(rga->cmdbuf_virt, 0, RGA_CMDBUF_SIZE * 4); + + rga_cmd_set_src_addr(ctx, rga->src_mmu_pages); + /* + * Due to hardware bug, + * src1 mmu also should be configured when using alpha blending. + */ + rga_cmd_set_src1_addr(ctx, rga->dst_mmu_pages); + + rga_cmd_set_dst_addr(ctx, rga->dst_mmu_pages); + rga_cmd_set_mode(ctx); + + rga_cmd_set_trans_info(ctx); + + rga_write(rga, RGA_CMD_BASE, rga->cmdbuf_phy); + + /* sync CMD buf for RGA */ + dma_sync_single_for_device(rga->dev, rga->cmdbuf_phy, + PAGE_SIZE, DMA_BIDIRECTIONAL); +} + +void rga_hw_start(struct rockchip_rga *rga) +{ + struct rga_ctx *ctx = rga->curr; + + rga_cmd_set(ctx); + + rga_write(rga, RGA_SYS_CTRL, 0x00); + + rga_write(rga, RGA_SYS_CTRL, 0x22); + + rga_write(rga, RGA_INT, 0x600); + + rga_write(rga, RGA_CMD_CTRL, 0x1); +} diff --git a/drivers/media/platform/rockchip/rga/rga-hw.h b/drivers/media/platform/rockchip/rga/rga-hw.h new file mode 100644 index 000000000000..ca3c204abe42 --- /dev/null +++ b/drivers/media/platform/rockchip/rga/rga-hw.h @@ -0,0 +1,437 @@ +/* + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd + * Author: Jacob Chen <jacob-chen@iotwrt.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ +#ifndef __RGA_HW_H__ +#define __RGA_HW_H__ + +#define RGA_CMDBUF_SIZE 0x20 + +/* Hardware limits */ +#define MAX_WIDTH 8192 +#define MAX_HEIGHT 8192 + +#define MIN_WIDTH 34 +#define MIN_HEIGHT 34 + +#define DEFAULT_WIDTH 100 +#define DEFAULT_HEIGHT 100 + +#define RGA_TIMEOUT 500 + +/* Registers address */ +#define RGA_SYS_CTRL 0x0000 +#define RGA_CMD_CTRL 0x0004 +#define RGA_CMD_BASE 0x0008 +#define RGA_INT 0x0010 +#define RGA_MMU_CTRL0 0x0014 +#define RGA_VERSION_INFO 0x0028 + +#define RGA_MODE_BASE_REG 0x0100 +#define RGA_MODE_MAX_REG 0x017C + +#define RGA_MODE_CTRL 0x0100 +#define RGA_SRC_INFO 0x0104 +#define RGA_SRC_Y_RGB_BASE_ADDR 0x0108 +#define RGA_SRC_CB_BASE_ADDR 0x010c +#define RGA_SRC_CR_BASE_ADDR 0x0110 +#define RGA_SRC1_RGB_BASE_ADDR 0x0114 +#define RGA_SRC_VIR_INFO 0x0118 +#define RGA_SRC_ACT_INFO 0x011c +#define RGA_SRC_X_FACTOR 0x0120 +#define RGA_SRC_Y_FACTOR 0x0124 +#define RGA_SRC_BG_COLOR 0x0128 +#define RGA_SRC_FG_COLOR 0x012c +#define RGA_SRC_TR_COLOR0 0x0130 +#define RGA_SRC_TR_COLOR1 0x0134 + +#define RGA_DST_INFO 0x0138 +#define RGA_DST_Y_RGB_BASE_ADDR 0x013c +#define RGA_DST_CB_BASE_ADDR 0x0140 +#define RGA_DST_CR_BASE_ADDR 0x0144 +#define RGA_DST_VIR_INFO 0x0148 +#define RGA_DST_ACT_INFO 0x014c + +#define RGA_ALPHA_CTRL0 0x0150 +#define RGA_ALPHA_CTRL1 0x0154 +#define RGA_FADING_CTRL 0x0158 +#define RGA_PAT_CON 0x015c +#define RGA_ROP_CON0 0x0160 +#define RGA_ROP_CON1 0x0164 +#define RGA_MASK_BASE 0x0168 + +#define RGA_MMU_CTRL1 0x016C +#define RGA_MMU_SRC_BASE 0x0170 +#define RGA_MMU_SRC1_BASE 0x0174 +#define RGA_MMU_DST_BASE 0x0178 + +/* Registers value */ +#define RGA_MODE_RENDER_BITBLT 0 +#define RGA_MODE_RENDER_COLOR_PALETTE 1 +#define RGA_MODE_RENDER_RECTANGLE_FILL 2 +#define RGA_MODE_RENDER_UPDATE_PALETTE_LUT_RAM 3 + +#define RGA_MODE_BITBLT_MODE_SRC_TO_DST 0 +#define RGA_MODE_BITBLT_MODE_SRC_SRC1_TO_DST 1 + +#define RGA_MODE_CF_ROP4_SOLID 0 +#define RGA_MODE_CF_ROP4_PATTERN 1 + +#define RGA_COLOR_FMT_ABGR8888 0 +#define RGA_COLOR_FMT_XBGR8888 1 +#define RGA_COLOR_FMT_RGB888 2 +#define RGA_COLOR_FMT_BGR565 4 +#define RGA_COLOR_FMT_ABGR1555 5 +#define RGA_COLOR_FMT_ABGR4444 6 +#define RGA_COLOR_FMT_YUV422SP 8 +#define RGA_COLOR_FMT_YUV422P 9 +#define RGA_COLOR_FMT_YUV420SP 10 +#define RGA_COLOR_FMT_YUV420P 11 +/* SRC_COLOR Palette */ +#define RGA_COLOR_FMT_CP_1BPP 12 +#define RGA_COLOR_FMT_CP_2BPP 13 +#define RGA_COLOR_FMT_CP_4BPP 14 +#define RGA_COLOR_FMT_CP_8BPP 15 +#define RGA_COLOR_FMT_MASK 15 + +#define RGA_COLOR_NONE_SWAP 0 +#define RGA_COLOR_RB_SWAP 1 +#define RGA_COLOR_ALPHA_SWAP 2 +#define RGA_COLOR_UV_SWAP 4 + +#define RGA_SRC_CSC_MODE_BYPASS 0 +#define RGA_SRC_CSC_MODE_BT601_R0 1 +#define RGA_SRC_CSC_MODE_BT601_R1 2 +#define RGA_SRC_CSC_MODE_BT709_R0 3 +#define RGA_SRC_CSC_MODE_BT709_R1 4 + +#define RGA_SRC_ROT_MODE_0_DEGREE 0 +#define RGA_SRC_ROT_MODE_90_DEGREE 1 +#define RGA_SRC_ROT_MODE_180_DEGREE 2 +#define RGA_SRC_ROT_MODE_270_DEGREE 3 + +#define RGA_SRC_MIRR_MODE_NO 0 +#define RGA_SRC_MIRR_MODE_X 1 +#define RGA_SRC_MIRR_MODE_Y 2 +#define RGA_SRC_MIRR_MODE_X_Y 3 + +#define RGA_SRC_HSCL_MODE_NO 0 +#define RGA_SRC_HSCL_MODE_DOWN 1 +#define RGA_SRC_HSCL_MODE_UP 2 + +#define RGA_SRC_VSCL_MODE_NO 0 +#define RGA_SRC_VSCL_MODE_DOWN 1 +#define RGA_SRC_VSCL_MODE_UP 2 + +#define RGA_SRC_TRANS_ENABLE_R 1 +#define RGA_SRC_TRANS_ENABLE_G 2 +#define RGA_SRC_TRANS_ENABLE_B 4 +#define RGA_SRC_TRANS_ENABLE_A 8 + +#define RGA_SRC_BIC_COE_SELEC_CATROM 0 +#define RGA_SRC_BIC_COE_SELEC_MITCHELL 1 +#define RGA_SRC_BIC_COE_SELEC_HERMITE 2 +#define RGA_SRC_BIC_COE_SELEC_BSPLINE 3 + +#define RGA_DST_DITHER_MODE_888_TO_666 0 +#define RGA_DST_DITHER_MODE_888_TO_565 1 +#define RGA_DST_DITHER_MODE_888_TO_555 2 +#define RGA_DST_DITHER_MODE_888_TO_444 3 + +#define RGA_DST_CSC_MODE_BYPASS 0 +#define RGA_DST_CSC_MODE_BT601_R0 1 +#define RGA_DST_CSC_MODE_BT601_R1 2 +#define RGA_DST_CSC_MODE_BT709_R0 3 + +#define RGA_ALPHA_ROP_MODE_2 0 +#define RGA_ALPHA_ROP_MODE_3 1 +#define RGA_ALPHA_ROP_MODE_4 2 + +#define RGA_ALPHA_SELECT_ALPHA 0 +#define RGA_ALPHA_SELECT_ROP 1 + +#define RGA_ALPHA_MASK_BIG_ENDIAN 0 +#define RGA_ALPHA_MASK_LITTLE_ENDIAN 1 + +#define RGA_ALPHA_NORMAL 0 +#define RGA_ALPHA_REVERSE 1 + +#define RGA_ALPHA_BLEND_GLOBAL 0 +#define RGA_ALPHA_BLEND_NORMAL 1 +#define RGA_ALPHA_BLEND_MULTIPLY 2 + +#define RGA_ALPHA_CAL_CUT 0 +#define RGA_ALPHA_CAL_NORMAL 1 + +#define RGA_ALPHA_FACTOR_ZERO 0 +#define RGA_ALPHA_FACTOR_ONE 1 +#define RGA_ALPHA_FACTOR_OTHER 2 +#define RGA_ALPHA_FACTOR_OTHER_REVERSE 3 +#define RGA_ALPHA_FACTOR_SELF 4 + +#define RGA_ALPHA_COLOR_NORMAL 0 +#define RGA_ALPHA_COLOR_MULTIPLY_CAL 1 + +/* Registers union */ +union rga_mode_ctrl { + unsigned int val; + struct { + /* [0:2] */ + unsigned int render:3; + /* [3:6] */ + unsigned int bitblt:1; + unsigned int cf_rop4_pat:1; + unsigned int alpha_zero_key:1; + unsigned int gradient_sat:1; + /* [7:31] */ + unsigned int reserved:25; + } data; +}; + +union rga_src_info { + unsigned int val; + struct { + /* [0:3] */ + unsigned int format:4; + /* [4:7] */ + unsigned int swap:3; + unsigned int cp_endian:1; + /* [8:17] */ + unsigned int csc_mode:2; + unsigned int rot_mode:2; + unsigned int mir_mode:2; + unsigned int hscl_mode:2; + unsigned int vscl_mode:2; + /* [18:22] */ + unsigned int trans_mode:1; + unsigned int trans_enable:4; + /* [23:25] */ + unsigned int dither_up_en:1; + unsigned int bic_coe_sel:2; + /* [26:31] */ + unsigned int reserved:6; + } data; +}; + +union rga_src_vir_info { + unsigned int val; + struct { + /* [0:15] */ + unsigned int vir_width:15; + unsigned int reserved:1; + /* [16:25] */ + unsigned int vir_stride:10; + /* [26:31] */ + unsigned int reserved1:6; + } data; +}; + +union rga_src_act_info { + unsigned int val; + struct { + /* [0:15] */ + unsigned int act_width:13; + unsigned int reserved:3; + /* [16:31] */ + unsigned int act_height:13; + unsigned int reserved1:3; + } data; +}; + +union rga_src_x_factor { + unsigned int val; + struct { + /* [0:15] */ + unsigned int down_scale_factor:16; + /* [16:31] */ + unsigned int up_scale_factor:16; + } data; +}; + +union rga_src_y_factor { + unsigned int val; + struct { + /* [0:15] */ + unsigned int down_scale_factor:16; + /* [16:31] */ + unsigned int up_scale_factor:16; + } data; +}; + +/* Alpha / Red / Green / Blue */ +union rga_src_cp_gr_color { + unsigned int val; + struct { + /* [0:15] */ + unsigned int gradient_x:16; + /* [16:31] */ + unsigned int gradient_y:16; + } data; +}; + +union rga_src_transparency_color0 { + unsigned int val; + struct { + /* [0:7] */ + unsigned int trans_rmin:8; + /* [8:15] */ + unsigned int trans_gmin:8; + /* [16:23] */ + unsigned int trans_bmin:8; + /* [24:31] */ + unsigned int trans_amin:8; + } data; +}; + +union rga_src_transparency_color1 { + unsigned int val; + struct { + /* [0:7] */ + unsigned int trans_rmax:8; + /* [8:15] */ + unsigned int trans_gmax:8; + /* [16:23] */ + unsigned int trans_bmax:8; + /* [24:31] */ + unsigned int trans_amax:8; + } data; +}; + +union rga_dst_info { + unsigned int val; + struct { + /* [0:3] */ + unsigned int format:4; + /* [4:6] */ + unsigned int swap:3; + /* [7:9] */ + unsigned int src1_format:3; + /* [10:11] */ + unsigned int src1_swap:2; + /* [12:15] */ + unsigned int dither_up_en:1; + unsigned int dither_down_en:1; + unsigned int dither_down_mode:2; + /* [16:18] */ + unsigned int csc_mode:2; + unsigned int csc_clip:1; + /* [19:31] */ + unsigned int reserved:13; + } data; +}; + +union rga_dst_vir_info { + unsigned int val; + struct { + /* [0:15] */ + unsigned int vir_stride:15; + unsigned int reserved:1; + /* [16:31] */ + unsigned int src1_vir_stride:15; + unsigned int reserved1:1; + } data; +}; + +union rga_dst_act_info { + unsigned int val; + struct { + /* [0:15] */ + unsigned int act_width:12; + unsigned int reserved:4; + /* [16:31] */ + unsigned int act_height:12; + unsigned int reserved1:4; + } data; +}; + +union rga_alpha_ctrl0 { + unsigned int val; + struct { + /* [0:3] */ + unsigned int rop_en:1; + unsigned int rop_select:1; + unsigned int rop_mode:2; + /* [4:11] */ + unsigned int src_fading_val:8; + /* [12:20] */ + unsigned int dst_fading_val:8; + unsigned int mask_endian:1; + /* [21:31] */ + unsigned int reserved:11; + } data; +}; + +union rga_alpha_ctrl1 { + unsigned int val; + struct { + /* [0:1] */ + unsigned int dst_color_m0:1; + unsigned int src_color_m0:1; + /* [2:7] */ + unsigned int dst_factor_m0:3; + unsigned int src_factor_m0:3; + /* [8:9] */ + unsigned int dst_alpha_cal_m0:1; + unsigned int src_alpha_cal_m0:1; + /* [10:13] */ + unsigned int dst_blend_m0:2; + unsigned int src_blend_m0:2; + /* [14:15] */ + unsigned int dst_alpha_m0:1; + unsigned int src_alpha_m0:1; + /* [16:21] */ + unsigned int dst_factor_m1:3; + unsigned int src_factor_m1:3; + /* [22:23] */ + unsigned int dst_alpha_cal_m1:1; + unsigned int src_alpha_cal_m1:1; + /* [24:27] */ + unsigned int dst_blend_m1:2; + unsigned int src_blend_m1:2; + /* [28:29] */ + unsigned int dst_alpha_m1:1; + unsigned int src_alpha_m1:1; + /* [30:31] */ + unsigned int reserved:2; + } data; +}; + +union rga_fading_ctrl { + unsigned int val; + struct { + /* [0:7] */ + unsigned int fading_offset_r:8; + /* [8:15] */ + unsigned int fading_offset_g:8; + /* [16:23] */ + unsigned int fading_offset_b:8; + /* [24:31] */ + unsigned int fading_en:1; + unsigned int reserved:7; + } data; +}; + +union rga_pat_con { + unsigned int val; + struct { + /* [0:7] */ + unsigned int width:8; + /* [8:15] */ + unsigned int height:8; + /* [16:23] */ + unsigned int offset_x:8; + /* [24:31] */ + unsigned int offset_y:8; + } data; +}; + +#endif diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c new file mode 100644 index 000000000000..89296de9cf4a --- /dev/null +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -0,0 +1,1010 @@ +/* + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd + * Author: Jacob Chen <jacob-chen@iotwrt.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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/clk.h> +#include <linux/debugfs.h> +#include <linux/delay.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/timer.h> + +#include <linux/platform_device.h> +#include <media/v4l2-device.h> +#include <media/v4l2-event.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-mem2mem.h> +#include <media/videobuf2-dma-sg.h> +#include <media/videobuf2-v4l2.h> + +#include "rga-hw.h" +#include "rga.h" + +static int debug; +module_param(debug, int, 0644); + +static void job_abort(void *prv) +{ + struct rga_ctx *ctx = prv; + struct rockchip_rga *rga = ctx->rga; + + if (!rga->curr) /* No job currently running */ + return; + + wait_event_timeout(rga->irq_queue, + !rga->curr, msecs_to_jiffies(RGA_TIMEOUT)); +} + +static void device_run(void *prv) +{ + struct rga_ctx *ctx = prv; + struct rockchip_rga *rga = ctx->rga; + struct vb2_buffer *src, *dst; + unsigned long flags; + + spin_lock_irqsave(&rga->ctrl_lock, flags); + + rga->curr = ctx; + + src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + + rga_buf_map(src); + rga_buf_map(dst); + + rga_hw_start(rga); + + spin_unlock_irqrestore(&rga->ctrl_lock, flags); +} + +static irqreturn_t rga_isr(int irq, void *prv) +{ + struct rockchip_rga *rga = prv; + int intr; + + intr = rga_read(rga, RGA_INT) & 0xf; + + rga_mod(rga, RGA_INT, intr << 4, 0xf << 4); + + if (intr & 0x04) { + struct vb2_v4l2_buffer *src, *dst; + struct rga_ctx *ctx = rga->curr; + + WARN_ON(!ctx); + + rga->curr = NULL; + + src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + + WARN_ON(!src); + WARN_ON(!dst); + + dst->timecode = src->timecode; + dst->vb2_buf.timestamp = src->vb2_buf.timestamp; + dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst->flags |= src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + + v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); + v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); + v4l2_m2m_job_finish(rga->m2m_dev, ctx->fh.m2m_ctx); + + wake_up(&rga->irq_queue); + } + + return IRQ_HANDLED; +} + +static struct v4l2_m2m_ops rga_m2m_ops = { + .device_run = device_run, + .job_abort = job_abort, +}; + +static int +queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) +{ + struct rga_ctx *ctx = priv; + int ret; + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->drv_priv = ctx; + src_vq->ops = &rga_qops; + src_vq->mem_ops = &vb2_dma_sg_memops; + src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->rga->mutex; + src_vq->dev = ctx->rga->v4l2_dev.dev; + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->drv_priv = ctx; + dst_vq->ops = &rga_qops; + dst_vq->mem_ops = &vb2_dma_sg_memops; + dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->rga->mutex; + dst_vq->dev = ctx->rga->v4l2_dev.dev; + + return vb2_queue_init(dst_vq); +} + +static int rga_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct rga_ctx *ctx = container_of(ctrl->handler, struct rga_ctx, + ctrl_handler); + unsigned long flags; + + spin_lock_irqsave(&ctx->rga->ctrl_lock, flags); + switch (ctrl->id) { + case V4L2_CID_HFLIP: + ctx->hflip = ctrl->val; + break; + case V4L2_CID_VFLIP: + ctx->vflip = ctrl->val; + break; + case V4L2_CID_ROTATE: + ctx->rotate = ctrl->val; + break; + case V4L2_CID_BG_COLOR: + ctx->fill_color = ctrl->val; + break; + } + spin_unlock_irqrestore(&ctx->rga->ctrl_lock, flags); + return 0; +} + +static const struct v4l2_ctrl_ops rga_ctrl_ops = { + .s_ctrl = rga_s_ctrl, +}; + +static int rga_setup_ctrls(struct rga_ctx *ctx) +{ + struct rockchip_rga *rga = ctx->rga; + + v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4); + + v4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + + v4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + v4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops, + V4L2_CID_ROTATE, 0, 270, 90, 0); + + v4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops, + V4L2_CID_BG_COLOR, 0, 0xffffffff, 1, 0); + + if (ctx->ctrl_handler.error) { + int err = ctx->ctrl_handler.error; + + v4l2_err(&rga->v4l2_dev, "%s failed\n", __func__); + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + return err; + } + + return 0; +} + +struct rga_fmt formats[] = { + { + .fourcc = V4L2_PIX_FMT_ARGB32, + .color_swap = RGA_COLOR_RB_SWAP, + .hw_format = RGA_COLOR_FMT_ABGR8888, + .depth = 32, + .uv_factor = 1, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_XRGB32, + .color_swap = RGA_COLOR_RB_SWAP, + .hw_format = RGA_COLOR_FMT_XBGR8888, + .depth = 32, + .uv_factor = 1, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_ABGR32, + .color_swap = RGA_COLOR_ALPHA_SWAP, + .hw_format = RGA_COLOR_FMT_ABGR8888, + .depth = 32, + .uv_factor = 1, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_XBGR32, + .color_swap = RGA_COLOR_ALPHA_SWAP, + .hw_format = RGA_COLOR_FMT_XBGR8888, + .depth = 32, + .uv_factor = 1, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_RGB24, + .color_swap = RGA_COLOR_NONE_SWAP, + .hw_format = RGA_COLOR_FMT_RGB888, + .depth = 24, + .uv_factor = 1, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_BGR24, + .color_swap = RGA_COLOR_RB_SWAP, + .hw_format = RGA_COLOR_FMT_RGB888, + .depth = 24, + .uv_factor = 1, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB444, + .color_swap = RGA_COLOR_RB_SWAP, + .hw_format = RGA_COLOR_FMT_ABGR4444, + .depth = 16, + .uv_factor = 1, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB555, + .color_swap = RGA_COLOR_RB_SWAP, + .hw_format = RGA_COLOR_FMT_ABGR1555, + .depth = 16, + .uv_factor = 1, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_RGB565, + .color_swap = RGA_COLOR_RB_SWAP, + .hw_format = RGA_COLOR_FMT_BGR565, + .depth = 16, + .uv_factor = 1, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_NV21, + .color_swap = RGA_COLOR_UV_SWAP, + .hw_format = RGA_COLOR_FMT_YUV420SP, + .depth = 12, + .uv_factor = 4, + .y_div = 2, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_NV61, + .color_swap = RGA_COLOR_UV_SWAP, + .hw_format = RGA_COLOR_FMT_YUV422SP, + .depth = 16, + .uv_factor = 2, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_NV12, + .color_swap = RGA_COLOR_NONE_SWAP, + .hw_format = RGA_COLOR_FMT_YUV420SP, + .depth = 12, + .uv_factor = 4, + .y_div = 2, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_NV16, + .color_swap = RGA_COLOR_NONE_SWAP, + .hw_format = RGA_COLOR_FMT_YUV422SP, + .depth = 16, + .uv_factor = 2, + .y_div = 1, + .x_div = 1, + }, + { + .fourcc = V4L2_PIX_FMT_YUV420, + .color_swap = RGA_COLOR_NONE_SWAP, + .hw_format = RGA_COLOR_FMT_YUV420P, + .depth = 12, + .uv_factor = 4, + .y_div = 2, + .x_div = 2, + }, + { + .fourcc = V4L2_PIX_FMT_YUV422P, + .color_swap = RGA_COLOR_NONE_SWAP, + .hw_format = RGA_COLOR_FMT_YUV422P, + .depth = 16, + .uv_factor = 2, + .y_div = 1, + .x_div = 2, + }, + { + .fourcc = V4L2_PIX_FMT_YVU420, + .color_swap = RGA_COLOR_UV_SWAP, + .hw_format = RGA_COLOR_FMT_YUV420P, + .depth = 12, + .uv_factor = 4, + .y_div = 2, + .x_div = 2, + }, +}; + +#define NUM_FORMATS ARRAY_SIZE(formats) + +static struct rga_fmt *rga_fmt_find(struct v4l2_format *f) +{ + unsigned int i; + + for (i = 0; i < NUM_FORMATS; i++) { + if (formats[i].fourcc == f->fmt.pix.pixelformat) + return &formats[i]; + } + return NULL; +} + +static struct rga_frame def_frame = { + .width = DEFAULT_WIDTH, + .height = DEFAULT_HEIGHT, + .colorspace = V4L2_COLORSPACE_DEFAULT, + .crop.left = 0, + .crop.top = 0, + .crop.width = DEFAULT_WIDTH, + .crop.height = DEFAULT_HEIGHT, + .fmt = &formats[0], +}; + +struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type type) +{ + switch (type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return &ctx->in; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return &ctx->out; + default: + return ERR_PTR(-EINVAL); + } +} + +static int rga_open(struct file *file) +{ + struct rockchip_rga *rga = video_drvdata(file); + struct rga_ctx *ctx = NULL; + int ret = 0; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->rga = rga; + /* Set default formats */ + ctx->in = def_frame; + ctx->out = def_frame; + + if (mutex_lock_interruptible(&rga->mutex)) { + kfree(ctx); + return -ERESTARTSYS; + } + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(rga->m2m_dev, ctx, &queue_init); + if (IS_ERR(ctx->fh.m2m_ctx)) { + ret = PTR_ERR(ctx->fh.m2m_ctx); + mutex_unlock(&rga->mutex); + kfree(ctx); + return ret; + } + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; + v4l2_fh_add(&ctx->fh); + + rga_setup_ctrls(ctx); + + /* Write the default values to the ctx struct */ + v4l2_ctrl_handler_setup(&ctx->ctrl_handler); + + ctx->fh.ctrl_handler = &ctx->ctrl_handler; + mutex_unlock(&rga->mutex); + + return 0; +} + +static int rga_release(struct file *file) +{ + struct rga_ctx *ctx = + container_of(file->private_data, struct rga_ctx, fh); + struct rockchip_rga *rga = ctx->rga; + + mutex_lock(&rga->mutex); + + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); + + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + kfree(ctx); + + mutex_unlock(&rga->mutex); + + return 0; +} + +static const struct v4l2_file_operations rga_fops = { + .owner = THIS_MODULE, + .open = rga_open, + .release = rga_release, + .poll = v4l2_m2m_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = v4l2_m2m_fop_mmap, +}; + +static int +vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) +{ + strlcpy(cap->driver, RGA_NAME, sizeof(cap->driver)); + strlcpy(cap->card, "rockchip-rga", sizeof(cap->card)); + strlcpy(cap->bus_info, "platform:rga", sizeof(cap->bus_info)); + + return 0; +} + +static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) +{ + struct rga_fmt *fmt; + + if (f->index >= NUM_FORMATS) + return -EINVAL; + + fmt = &formats[f->index]; + f->pixelformat = fmt->fourcc; + + return 0; +} + +static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) +{ + struct rga_ctx *ctx = prv; + struct vb2_queue *vq; + struct rga_frame *frm; + + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + if (!vq) + return -EINVAL; + frm = rga_get_frame(ctx, f->type); + if (IS_ERR(frm)) + return PTR_ERR(frm); + + f->fmt.pix.width = frm->width; + f->fmt.pix.height = frm->height; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.pixelformat = frm->fmt->fourcc; + f->fmt.pix.bytesperline = frm->stride; + f->fmt.pix.sizeimage = frm->size; + f->fmt.pix.colorspace = frm->colorspace; + + return 0; +} + +static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) +{ + struct rga_fmt *fmt; + + fmt = rga_fmt_find(f); + if (!fmt) { + fmt = &formats[0]; + f->fmt.pix.pixelformat = fmt->fourcc; + } + + f->fmt.pix.field = V4L2_FIELD_NONE; + + if (f->fmt.pix.width > MAX_WIDTH) + f->fmt.pix.width = MAX_WIDTH; + if (f->fmt.pix.height > MAX_HEIGHT) + f->fmt.pix.height = MAX_HEIGHT; + + if (f->fmt.pix.width < MIN_WIDTH) + f->fmt.pix.width = MIN_WIDTH; + if (f->fmt.pix.height < MIN_HEIGHT) + f->fmt.pix.height = MIN_HEIGHT; + + if (fmt->hw_format >= RGA_COLOR_FMT_YUV422SP) + f->fmt.pix.bytesperline = f->fmt.pix.width; + else + f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; + + f->fmt.pix.sizeimage = + f->fmt.pix.height * (f->fmt.pix.width * fmt->depth) >> 3; + + return 0; +} + +static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) +{ + struct rga_ctx *ctx = prv; + struct rockchip_rga *rga = ctx->rga; + struct vb2_queue *vq; + struct rga_frame *frm; + struct rga_fmt *fmt; + int ret = 0; + + /* Adjust all values accordingly to the hardware capabilities + * and chosen format. + */ + ret = vidioc_try_fmt(file, prv, f); + if (ret) + return ret; + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + if (vb2_is_busy(vq)) { + v4l2_err(&rga->v4l2_dev, "queue (%d) bust\n", f->type); + return -EBUSY; + } + frm = rga_get_frame(ctx, f->type); + if (IS_ERR(frm)) + return PTR_ERR(frm); + fmt = rga_fmt_find(f); + if (!fmt) + return -EINVAL; + frm->width = f->fmt.pix.width; + frm->height = f->fmt.pix.height; + frm->size = f->fmt.pix.sizeimage; + frm->fmt = fmt; + frm->stride = f->fmt.pix.bytesperline; + frm->colorspace = f->fmt.pix.colorspace; + + /* Reset crop settings */ + frm->crop.left = 0; + frm->crop.top = 0; + frm->crop.width = frm->width; + frm->crop.height = frm->height; + + return 0; +} + +static int vidioc_g_selection(struct file *file, void *prv, + struct v4l2_selection *s) +{ + struct rga_ctx *ctx = prv; + struct rga_frame *f; + bool use_frame = false; + + f = rga_get_frame(ctx, s->type); + if (IS_ERR(f)) + return PTR_ERR(f); + + switch (s->target) { + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + break; + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + break; + case V4L2_SEL_TGT_COMPOSE: + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + use_frame = true; + break; + case V4L2_SEL_TGT_CROP: + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + use_frame = true; + break; + default: + return -EINVAL; + } + + if (use_frame) { + s->r = f->crop; + } else { + s->r.left = 0; + s->r.top = 0; + s->r.width = f->width; + s->r.height = f->height; + } + + return 0; +} + +static int vidioc_s_selection(struct file *file, void *prv, + struct v4l2_selection *s) +{ + struct rga_ctx *ctx = prv; + struct rockchip_rga *rga = ctx->rga; + struct rga_frame *f; + int ret = 0; + + f = rga_get_frame(ctx, s->type); + if (IS_ERR(f)) + return PTR_ERR(f); + + switch (s->target) { + case V4L2_SEL_TGT_COMPOSE: + /* + * COMPOSE target is only valid for capture buffer type, return + * error for output buffer type + */ + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + break; + case V4L2_SEL_TGT_CROP: + /* + * CROP target is only valid for output buffer type, return + * error for capture buffer type + */ + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + break; + /* + * bound and default crop/compose targets are invalid targets to + * try/set + */ + default: + return -EINVAL; + } + + if (s->r.top < 0 || s->r.left < 0) { + v4l2_dbg(debug, 1, &rga->v4l2_dev, + "doesn't support negative values for top & left.\n"); + return -EINVAL; + } + + if (s->r.left + s->r.width > f->width || + s->r.top + s->r.height > f->height || + s->r.width < MIN_WIDTH || s->r.height < MIN_HEIGHT) { + v4l2_dbg(debug, 1, &rga->v4l2_dev, "unsupported crop value.\n"); + return -EINVAL; + } + + f->crop = s->r; + + return ret; +} + +static const struct v4l2_ioctl_ops rga_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt, + + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt, + .vidioc_g_fmt_vid_out = vidioc_g_fmt, + .vidioc_try_fmt_vid_out = vidioc_try_fmt, + .vidioc_s_fmt_vid_out = vidioc_s_fmt, + + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, + + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + + .vidioc_g_selection = vidioc_g_selection, + .vidioc_s_selection = vidioc_s_selection, +}; + +static struct video_device rga_videodev = { + .name = "rockchip-rga", + .fops = &rga_fops, + .ioctl_ops = &rga_ioctl_ops, + .minor = -1, + .release = video_device_release, + .vfl_dir = VFL_DIR_M2M, + .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING, +}; + +static int rga_enable_clocks(struct rockchip_rga *rga) +{ + int ret; + + ret = clk_prepare_enable(rga->sclk); + if (ret) { + dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(rga->aclk); + if (ret) { + dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret); + goto err_disable_sclk; + } + + ret = clk_prepare_enable(rga->hclk); + if (ret) { + dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret); + goto err_disable_aclk; + } + + return 0; + +err_disable_sclk: + clk_disable_unprepare(rga->sclk); +err_disable_aclk: + clk_disable_unprepare(rga->aclk); + + return ret; +} + +static void rga_disable_clocks(struct rockchip_rga *rga) +{ + clk_disable_unprepare(rga->sclk); + clk_disable_unprepare(rga->hclk); + clk_disable_unprepare(rga->aclk); +} + +static int rga_parse_dt(struct rockchip_rga *rga) +{ + struct reset_control *core_rst, *axi_rst, *ahb_rst; + + core_rst = devm_reset_control_get(rga->dev, "core"); + if (IS_ERR(core_rst)) { + dev_err(rga->dev, "failed to get core reset controller\n"); + return PTR_ERR(core_rst); + } + + axi_rst = devm_reset_control_get(rga->dev, "axi"); + if (IS_ERR(axi_rst)) { + dev_err(rga->dev, "failed to get axi reset controller\n"); + return PTR_ERR(axi_rst); + } + + ahb_rst = devm_reset_control_get(rga->dev, "ahb"); + if (IS_ERR(ahb_rst)) { + dev_err(rga->dev, "failed to get ahb reset controller\n"); + return PTR_ERR(ahb_rst); + } + + reset_control_assert(core_rst); + udelay(1); + reset_control_deassert(core_rst); + + reset_control_assert(axi_rst); + udelay(1); + reset_control_deassert(axi_rst); + + reset_control_assert(ahb_rst); + udelay(1); + reset_control_deassert(ahb_rst); + + rga->sclk = devm_clk_get(rga->dev, "sclk"); + if (IS_ERR(rga->sclk)) { + dev_err(rga->dev, "failed to get sclk clock\n"); + return PTR_ERR(rga->sclk); + } + + rga->aclk = devm_clk_get(rga->dev, "aclk"); + if (IS_ERR(rga->aclk)) { + dev_err(rga->dev, "failed to get aclk clock\n"); + return PTR_ERR(rga->aclk); + } + + rga->hclk = devm_clk_get(rga->dev, "hclk"); + if (IS_ERR(rga->hclk)) { + dev_err(rga->dev, "failed to get hclk clock\n"); + return PTR_ERR(rga->hclk); + } + + return 0; +} + +static int rga_probe(struct platform_device *pdev) +{ + struct rockchip_rga *rga; + struct video_device *vfd; + struct resource *res; + int ret = 0; + int irq; + + if (!pdev->dev.of_node) + return -ENODEV; + + rga = devm_kzalloc(&pdev->dev, sizeof(*rga), GFP_KERNEL); + if (!rga) + return -ENOMEM; + + rga->dev = &pdev->dev; + spin_lock_init(&rga->ctrl_lock); + mutex_init(&rga->mutex); + + init_waitqueue_head(&rga->irq_queue); + + ret = rga_parse_dt(rga); + if (ret) + dev_err(&pdev->dev, "Unable to parse OF data\n"); + + pm_runtime_enable(rga->dev); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + rga->regs = devm_ioremap_resource(rga->dev, res); + if (IS_ERR(rga->regs)) { + ret = PTR_ERR(rga->regs); + goto err_put_clk; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(rga->dev, "failed to get irq\n"); + ret = irq; + goto err_put_clk; + } + + ret = devm_request_irq(rga->dev, irq, rga_isr, 0, + dev_name(rga->dev), rga); + if (ret < 0) { + dev_err(rga->dev, "failed to request irq\n"); + goto err_put_clk; + } + + ret = v4l2_device_register(&pdev->dev, &rga->v4l2_dev); + if (ret) + goto err_put_clk; + vfd = video_device_alloc(); + if (!vfd) { + v4l2_err(&rga->v4l2_dev, "Failed to allocate video device\n"); + ret = -ENOMEM; + goto unreg_v4l2_dev; + } + *vfd = rga_videodev; + vfd->lock = &rga->mutex; + vfd->v4l2_dev = &rga->v4l2_dev; + + video_set_drvdata(vfd, rga); + snprintf(vfd->name, sizeof(vfd->name), "%s", rga_videodev.name); + rga->vfd = vfd; + + platform_set_drvdata(pdev, rga); + rga->m2m_dev = v4l2_m2m_init(&rga_m2m_ops); + if (IS_ERR(rga->m2m_dev)) { + v4l2_err(&rga->v4l2_dev, "Failed to init mem2mem device\n"); + ret = PTR_ERR(rga->m2m_dev); + goto unreg_video_dev; + } + + pm_runtime_get_sync(rga->dev); + + rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF; + rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F; + + v4l2_info(&rga->v4l2_dev, "HW Version: 0x%02x.%02x\n", + rga->version.major, rga->version.minor); + + pm_runtime_put(rga->dev); + + /* Create CMD buffer */ + rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, RGA_CMDBUF_SIZE, + &rga->cmdbuf_phy, GFP_KERNEL, + DMA_ATTR_WRITE_COMBINE); + + rga->src_mmu_pages = + (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3); + rga->dst_mmu_pages = + (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3); + + def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; + def_frame.size = def_frame.stride * def_frame.height; + + ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); + if (ret) { + v4l2_err(&rga->v4l2_dev, "Failed to register video device\n"); + goto rel_vdev; + } + + v4l2_info(&rga->v4l2_dev, "Registered %s as /dev/%s\n", + vfd->name, video_device_node_name(vfd)); + + return 0; + +rel_vdev: + video_device_release(vfd); +unreg_video_dev: + video_unregister_device(rga->vfd); +unreg_v4l2_dev: + v4l2_device_unregister(&rga->v4l2_dev); +err_put_clk: + pm_runtime_disable(rga->dev); + + return ret; +} + +static int rga_remove(struct platform_device *pdev) +{ + struct rockchip_rga *rga = platform_get_drvdata(pdev); + + dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, &rga->cmdbuf_virt, + rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE); + + free_pages((unsigned long)rga->src_mmu_pages, 3); + free_pages((unsigned long)rga->dst_mmu_pages, 3); + + v4l2_info(&rga->v4l2_dev, "Removing\n"); + + v4l2_m2m_release(rga->m2m_dev); + video_unregister_device(rga->vfd); + v4l2_device_unregister(&rga->v4l2_dev); + + pm_runtime_disable(rga->dev); + + return 0; +} + +static int __maybe_unused rga_runtime_suspend(struct device *dev) +{ + struct rockchip_rga *rga = dev_get_drvdata(dev); + + rga_disable_clocks(rga); + + return 0; +} + +static int __maybe_unused rga_runtime_resume(struct device *dev) +{ + struct rockchip_rga *rga = dev_get_drvdata(dev); + + return rga_enable_clocks(rga); +} + +static const struct dev_pm_ops rga_pm = { + SET_RUNTIME_PM_OPS(rga_runtime_suspend, + rga_runtime_resume, NULL) +}; + +static const struct of_device_id rockchip_rga_match[] = { + { + .compatible = "rockchip,rk3288-rga", + }, + { + .compatible = "rockchip,rk3399-rga", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, rockchip_rga_match); + +static struct platform_driver rga_pdrv = { + .probe = rga_probe, + .remove = rga_remove, + .driver = { + .name = RGA_NAME, + .pm = &rga_pm, + .of_match_table = rockchip_rga_match, + }, +}; + +module_platform_driver(rga_pdrv); + +MODULE_AUTHOR("Jacob Chen <jacob-chen@iotwrt.com>"); +MODULE_DESCRIPTION("Rockchip Raster 2d Graphic Acceleration Unit"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h new file mode 100644 index 000000000000..5d43e7ea88af --- /dev/null +++ b/drivers/media/platform/rockchip/rga/rga.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd + * Author: Jacob Chen <jacob-chen@iotwrt.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ +#ifndef __RGA_H__ +#define __RGA_H__ + +#include <linux/platform_device.h> +#include <media/videobuf2-v4l2.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> + +#define RGA_NAME "rockchip-rga" + +struct rga_fmt { + u32 fourcc; + int depth; + u8 uv_factor; + u8 y_div; + u8 x_div; + u8 color_swap; + u8 hw_format; +}; + +struct rga_frame { + /* Original dimensions */ + u32 width; + u32 height; + u32 colorspace; + + /* Crop */ + struct v4l2_rect crop; + + /* Image format */ + struct rga_fmt *fmt; + + /* Variables that can calculated once and reused */ + u32 stride; + u32 size; +}; + +struct rockchip_rga_version { + u32 major; + u32 minor; +}; + +struct rga_ctx { + struct v4l2_fh fh; + struct rockchip_rga *rga; + struct rga_frame in; + struct rga_frame out; + struct v4l2_ctrl_handler ctrl_handler; + + /* Control values */ + u32 op; + u32 hflip; + u32 vflip; + u32 rotate; + u32 fill_color; +}; + +struct rockchip_rga { + struct v4l2_device v4l2_dev; + struct v4l2_m2m_dev *m2m_dev; + struct video_device *vfd; + + struct device *dev; + struct regmap *grf; + void __iomem *regs; + struct clk *sclk; + struct clk *aclk; + struct clk *hclk; + struct rockchip_rga_version version; + + /* vfd lock */ + struct mutex mutex; + /* ctrl parm lock */ + spinlock_t ctrl_lock; + + wait_queue_head_t irq_queue; + + struct rga_ctx *curr; + dma_addr_t cmdbuf_phy; + void *cmdbuf_virt; + unsigned int *src_mmu_pages; + unsigned int *dst_mmu_pages; +}; + +struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type type); + +/* RGA Buffers Manage */ +extern const struct vb2_ops rga_qops; +void rga_buf_map(struct vb2_buffer *vb); + +/* RGA Hardware */ +static inline void rga_write(struct rockchip_rga *rga, u32 reg, u32 value) +{ + writel(value, rga->regs + reg); +}; + +static inline u32 rga_read(struct rockchip_rga *rga, u32 reg) +{ + return readl(rga->regs + reg); +}; + +static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask) +{ + u32 temp = rga_read(rga, reg) & ~(mask); + + temp |= val & mask; + rga_write(rga, reg, temp); +}; + +void rga_hw_start(struct rockchip_rga *rga); + +#endif diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c index c4ab63986c8f..79bc0ef6bb41 100644 --- a/drivers/media/platform/s3c-camif/camif-core.c +++ b/drivers/media/platform/s3c-camif/camif-core.c @@ -103,6 +103,7 @@ static const struct camif_fmt camif_formats[] = { /** * s3c_camif_find_format() - lookup camif color format by fourcc or an index + * @vp: video path (DMA) description (codec/preview) * @pixelformat: fourcc to match, ignored if null * @index: index to the camif_formats array, ignored if negative */ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 1afde5021ca6..bc68dbbcaec1 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -145,9 +145,9 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq) } } -static void s5p_mfc_watchdog(unsigned long arg) +static void s5p_mfc_watchdog(struct timer_list *t) { - struct s5p_mfc_dev *dev = (struct s5p_mfc_dev *)arg; + struct s5p_mfc_dev *dev = from_timer(dev, t, watchdog_timer); if (test_bit(0, &dev->hw_lock)) atomic_inc(&dev->watchdog_cnt); @@ -470,7 +470,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, { mfc_err("Interrupt Error: %08x\n", err); - if (ctx != NULL) { + if (ctx) { /* Error recovery is dependent on the state of context */ switch (ctx->state) { case MFCINST_RES_CHANGE_INIT: @@ -508,7 +508,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, { struct s5p_mfc_dev *dev; - if (ctx == NULL) + if (!ctx) return; dev = ctx->dev; if (ctx->c_ops->post_seq_start) { @@ -562,7 +562,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *src_buf; struct s5p_mfc_dev *dev; - if (ctx == NULL) + if (!ctx) return; dev = ctx->dev; s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); @@ -1043,12 +1043,9 @@ end: static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma) { struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); - struct s5p_mfc_dev *dev = ctx->dev; unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; int ret; - if (mutex_lock_interruptible(&dev->mfc_mutex)) - return -ERESTARTSYS; if (offset < DST_QUEUE_OFF_BASE) { mfc_debug(2, "mmaping source\n"); ret = vb2_mmap(&ctx->vq_src, vma); @@ -1057,7 +1054,6 @@ static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT); ret = vb2_mmap(&ctx->vq_dst, vma); } - mutex_unlock(&dev->mfc_mutex); return ret; } @@ -1083,7 +1079,7 @@ static struct device *s5p_mfc_alloc_memdev(struct device *dev, struct device *child; int ret; - child = devm_kzalloc(dev, sizeof(struct device), GFP_KERNEL); + child = devm_kzalloc(dev, sizeof(*child), GFP_KERNEL); if (!child) return NULL; @@ -1270,10 +1266,8 @@ static int s5p_mfc_probe(struct platform_device *pdev) pr_debug("%s++\n", __func__); dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); - if (!dev) { - dev_err(&pdev->dev, "Not enough memory for MFC device\n"); + if (!dev) return -ENOMEM; - } spin_lock_init(&dev->irqlock); spin_lock_init(&dev->condlock); @@ -1291,7 +1285,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) return PTR_ERR(dev->regs_base); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res == NULL) { + if (!res) { dev_err(&pdev->dev, "failed to get irq resource\n"); return -ENOENT; } @@ -1320,9 +1314,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) dev->hw_lock = 0; INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker); atomic_set(&dev->watchdog_cnt, 0); - init_timer(&dev->watchdog_timer); - dev->watchdog_timer.data = (unsigned long)dev; - dev->watchdog_timer.function = s5p_mfc_watchdog; + timer_setup(&dev->watchdog_timer, s5p_mfc_watchdog, 0); ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 15a562af13c7..dedc1b024f6f 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -267,7 +267,7 @@ static void sh_veu_process(struct sh_veu_dev *veu, sh_veu_reg_write(veu, VEU_EIER, 1); /* enable interrupt in VEU */ } -/** +/* * sh_veu_device_run() - prepares and starts the device * * This will be called by the framework when it decides to schedule a particular diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 1f3c450c7a69..916ff68b73d4 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -1391,6 +1391,12 @@ static int soc_camera_async_complete(struct v4l2_async_notifier *notifier) return 0; } +static const struct v4l2_async_notifier_operations soc_camera_async_ops = { + .bound = soc_camera_async_bound, + .unbind = soc_camera_async_unbind, + .complete = soc_camera_async_complete, +}; + static int scan_async_group(struct soc_camera_host *ici, struct v4l2_async_subdev **asd, unsigned int size) { @@ -1437,9 +1443,7 @@ static int scan_async_group(struct soc_camera_host *ici, sasc->notifier.subdevs = asd; sasc->notifier.num_subdevs = size; - sasc->notifier.bound = soc_camera_async_bound; - sasc->notifier.unbind = soc_camera_async_unbind; - sasc->notifier.complete = soc_camera_async_complete; + sasc->notifier.ops = &soc_camera_async_ops; icd->sasc = sasc; icd->parent = ici->v4l2_dev.dev; @@ -1537,9 +1541,7 @@ static int soc_of_bind(struct soc_camera_host *ici, sasc->notifier.subdevs = &info->subdev; sasc->notifier.num_subdevs = 1; - sasc->notifier.bound = soc_camera_async_bound; - sasc->notifier.unbind = soc_camera_async_unbind; - sasc->notifier.complete = soc_camera_async_complete; + sasc->notifier.ops = &soc_camera_async_ops; icd->sasc = sasc; icd->parent = ici->v4l2_dev.dev; diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c index 0116097c0c0f..270ec613c27c 100644 --- a/drivers/media/platform/soc_camera/soc_scale_crop.c +++ b/drivers/media/platform/soc_camera/soc_scale_crop.c @@ -306,16 +306,17 @@ update_cache: } /** - * @icd - soc-camera device - * @rect - camera cropping window - * @subrect - part of rect, sent to the user - * @mf - in- / output camera output window - * @width - on input: max host input width - * on output: user width, mapped back to input - * @height - on input: max host input height - * on output: user height, mapped back to input - * @host_can_scale - host can scale this pixel format - * @shift - shift, used for scaling + * soc_camera_client_scale + * @icd: soc-camera device + * @rect: camera cropping window + * @subrect: part of rect, sent to the user + * @mf: in- / output camera output window + * @width: on input: max host input width; + * on output: user width, mapped back to input + * @height: on input: max host input height; + * on output: user height, mapped back to input + * @host_can_scale: host can scale this pixel format + * @shift: shift, used for scaling */ int soc_camera_client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, struct v4l2_rect *subrect, diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c index 939da6da7644..7e9ed9c7b3e1 100644 --- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c @@ -723,7 +723,7 @@ static int bdisp_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) static int bdisp_g_fmt(struct file *file, void *fh, struct v4l2_format *f) { struct bdisp_ctx *ctx = fh_to_ctx(fh); - struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_pix_format *pix; struct bdisp_frame *frame = ctx_get_frame(ctx, f->type); if (IS_ERR(frame)) { diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c index 59280ac31937..a0acee7671b1 100644 --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c @@ -61,9 +61,9 @@ static int load_c8sectpfe_fw(struct c8sectpfei *fei); #define FIFO_LEN 1024 -static void c8sectpfe_timer_interrupt(unsigned long ac8sectpfei) +static void c8sectpfe_timer_interrupt(struct timer_list *t) { - struct c8sectpfei *fei = (struct c8sectpfei *)ac8sectpfei; + struct c8sectpfei *fei = from_timer(fei, t, timer); struct channel_info *channel; int chan_num; @@ -865,8 +865,7 @@ static int c8sectpfe_probe(struct platform_device *pdev) } /* Setup timer interrupt */ - setup_timer(&fei->timer, c8sectpfe_timer_interrupt, - (unsigned long)fei); + timer_setup(&fei->timer, c8sectpfe_timer_interrupt, 0); mutex_init(&fei->lock); diff --git a/drivers/media/platform/sti/hva/hva-h264.c b/drivers/media/platform/sti/hva/hva-h264.c index e6f247a983c7..17f1eb0ba957 100644 --- a/drivers/media/platform/sti/hva/hva-h264.c +++ b/drivers/media/platform/sti/hva/hva-h264.c @@ -134,7 +134,7 @@ enum hva_h264_sei_payload_type { SEI_FRAME_PACKING_ARRANGEMENT = 45 }; -/** +/* * stereo Video Info struct */ struct hva_h264_stereo_video_sei { @@ -146,7 +146,9 @@ struct hva_h264_stereo_video_sei { u8 right_view_self_contained_flag; }; -/** +/* + * struct hva_h264_td + * * @frame_width: width in pixels of the buffer containing the input frame * @frame_height: height in pixels of the buffer containing the input frame * @frame_num: the parameter to be written in the slice header @@ -352,7 +354,9 @@ struct hva_h264_td { u32 addr_brc_in_out_parameter; }; -/** +/* + * struct hva_h264_slice_po + * * @ slice_size: slice size * @ slice_start_time: start time * @ slice_stop_time: stop time @@ -365,7 +369,9 @@ struct hva_h264_slice_po { u32 slice_num; }; -/** +/* + * struct hva_h264_po + * * @ bitstream_size: bitstream size * @ dct_bitstream_size: dtc bitstream size * @ stuffing_bits: number of stuffing bits inserted by the encoder @@ -391,7 +397,9 @@ struct hva_h264_task { struct hva_h264_po po; }; -/** +/* + * struct hva_h264_ctx + * * @seq_info: sequence information buffer * @ref_frame: reference frame buffer * @rec_frame: reconstructed frame buffer @@ -999,7 +1007,6 @@ static int hva_h264_encode(struct hva_ctx *pctx, struct hva_frame *frame, { struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; struct hva_h264_task *task = (struct hva_h264_task *)ctx->task->vaddr; - struct hva_buffer *tmp_frame; u32 stuffing_bytes = 0; int ret = 0; @@ -1023,9 +1030,7 @@ static int hva_h264_encode(struct hva_ctx *pctx, struct hva_frame *frame, &stream->bytesused); /* switch reference & reconstructed frame */ - tmp_frame = ctx->ref_frame; - ctx->ref_frame = ctx->rec_frame; - ctx->rec_frame = tmp_frame; + swap(ctx->ref_frame, ctx->rec_frame); return 0; err: diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index 35ba6f211b79..ac4c450a6c7d 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -1495,6 +1495,12 @@ static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier, return 0; } +static const struct v4l2_async_notifier_operations dcmi_graph_notify_ops = { + .bound = dcmi_graph_notify_bound, + .unbind = dcmi_graph_notify_unbind, + .complete = dcmi_graph_notify_complete, +}; + static int dcmi_graph_parse(struct stm32_dcmi *dcmi, struct device_node *node) { struct device_node *ep = NULL; @@ -1542,9 +1548,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi) dcmi->notifier.subdevs = subdevs; dcmi->notifier.num_subdevs = 1; - dcmi->notifier.bound = dcmi_graph_notify_bound; - dcmi->notifier.unbind = dcmi_graph_notify_unbind; - dcmi->notifier.complete = dcmi_graph_notify_complete; + dcmi->notifier.ops = &dcmi_graph_notify_ops; ret = v4l2_async_notifier_register(&dcmi->v4l2_dev, &dcmi->notifier); if (ret < 0) { diff --git a/drivers/media/platform/tegra-cec/Makefile b/drivers/media/platform/tegra-cec/Makefile new file mode 100644 index 000000000000..f3d81127589f --- /dev/null +++ b/drivers/media/platform/tegra-cec/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VIDEO_TEGRA_HDMI_CEC) += tegra_cec.o diff --git a/drivers/media/platform/tegra-cec/tegra_cec.c b/drivers/media/platform/tegra-cec/tegra_cec.c new file mode 100644 index 000000000000..807c94c70049 --- /dev/null +++ b/drivers/media/platform/tegra-cec/tegra_cec.c @@ -0,0 +1,495 @@ +/* + * Tegra CEC implementation + * + * The original 3.10 CEC driver using a custom API: + * + * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved. + * + * Conversion to the CEC framework and to the mainline kernel: + * + * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/clk/tegra.h> + +#include <media/cec-notifier.h> + +#include "tegra_cec.h" + +#define TEGRA_CEC_NAME "tegra-cec" + +struct tegra_cec { + struct cec_adapter *adap; + struct device *dev; + struct clk *clk; + void __iomem *cec_base; + struct cec_notifier *notifier; + int tegra_cec_irq; + bool rx_done; + bool tx_done; + int tx_status; + u8 rx_buf[CEC_MAX_MSG_SIZE]; + u8 rx_buf_cnt; + u32 tx_buf[CEC_MAX_MSG_SIZE]; + u8 tx_buf_cur; + u8 tx_buf_cnt; +}; + +static inline u32 cec_read(struct tegra_cec *cec, u32 reg) +{ + return readl(cec->cec_base + reg); +} + +static inline void cec_write(struct tegra_cec *cec, u32 reg, u32 val) +{ + writel(val, cec->cec_base + reg); +} + +static void tegra_cec_error_recovery(struct tegra_cec *cec) +{ + u32 hw_ctrl; + + hw_ctrl = cec_read(cec, TEGRA_CEC_HW_CONTROL); + cec_write(cec, TEGRA_CEC_HW_CONTROL, 0); + cec_write(cec, TEGRA_CEC_INT_STAT, 0xffffffff); + cec_write(cec, TEGRA_CEC_HW_CONTROL, hw_ctrl); +} + +static irqreturn_t tegra_cec_irq_thread_handler(int irq, void *data) +{ + struct device *dev = data; + struct tegra_cec *cec = dev_get_drvdata(dev); + + if (cec->tx_done) { + cec_transmit_attempt_done(cec->adap, cec->tx_status); + cec->tx_done = false; + } + if (cec->rx_done) { + struct cec_msg msg = {}; + + msg.len = cec->rx_buf_cnt; + memcpy(msg.msg, cec->rx_buf, msg.len); + cec_received_msg(cec->adap, &msg); + cec->rx_done = false; + cec->rx_buf_cnt = 0; + } + return IRQ_HANDLED; +} + +static irqreturn_t tegra_cec_irq_handler(int irq, void *data) +{ + struct device *dev = data; + struct tegra_cec *cec = dev_get_drvdata(dev); + u32 status, mask; + + status = cec_read(cec, TEGRA_CEC_INT_STAT); + mask = cec_read(cec, TEGRA_CEC_INT_MASK); + + status &= mask; + + if (!status) + return IRQ_HANDLED; + + if (status & TEGRA_CEC_INT_STAT_TX_REGISTER_UNDERRUN) { + dev_err(dev, "TX underrun, interrupt timing issue!\n"); + + tegra_cec_error_recovery(cec); + cec_write(cec, TEGRA_CEC_INT_MASK, + mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY); + + cec->tx_done = true; + cec->tx_status = CEC_TX_STATUS_ERROR; + return IRQ_WAKE_THREAD; + } + + if ((status & TEGRA_CEC_INT_STAT_TX_ARBITRATION_FAILED) || + (status & TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED)) { + tegra_cec_error_recovery(cec); + cec_write(cec, TEGRA_CEC_INT_MASK, + mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY); + + cec->tx_done = true; + if (status & TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED) + cec->tx_status = CEC_TX_STATUS_LOW_DRIVE; + else + cec->tx_status = CEC_TX_STATUS_ARB_LOST; + return IRQ_WAKE_THREAD; + } + + if (status & TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED) { + cec_write(cec, TEGRA_CEC_INT_STAT, + TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED); + + if (status & TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD) { + tegra_cec_error_recovery(cec); + + cec->tx_done = true; + cec->tx_status = CEC_TX_STATUS_NACK; + } else { + cec->tx_done = true; + cec->tx_status = CEC_TX_STATUS_OK; + } + return IRQ_WAKE_THREAD; + } + + if (status & TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD) + dev_warn(dev, "TX NAKed on the fly!\n"); + + if (status & TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY) { + if (cec->tx_buf_cur == cec->tx_buf_cnt) { + cec_write(cec, TEGRA_CEC_INT_MASK, + mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY); + } else { + cec_write(cec, TEGRA_CEC_TX_REGISTER, + cec->tx_buf[cec->tx_buf_cur++]); + cec_write(cec, TEGRA_CEC_INT_STAT, + TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY); + } + } + + if (status & (TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN | + TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED | + TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED | + TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED)) { + cec_write(cec, TEGRA_CEC_INT_STAT, + (TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN | + TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED | + TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED | + TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED)); + } else if (status & TEGRA_CEC_INT_STAT_RX_REGISTER_FULL) { + u32 v; + + cec_write(cec, TEGRA_CEC_INT_STAT, + TEGRA_CEC_INT_STAT_RX_REGISTER_FULL); + v = cec_read(cec, TEGRA_CEC_RX_REGISTER); + if (cec->rx_buf_cnt < CEC_MAX_MSG_SIZE) + cec->rx_buf[cec->rx_buf_cnt++] = v & 0xff; + if (v & TEGRA_CEC_RX_REGISTER_EOM) { + cec->rx_done = true; + return IRQ_WAKE_THREAD; + } + } + + return IRQ_HANDLED; +} + +static int tegra_cec_adap_enable(struct cec_adapter *adap, bool enable) +{ + struct tegra_cec *cec = adap->priv; + + cec->rx_buf_cnt = 0; + cec->tx_buf_cnt = 0; + cec->tx_buf_cur = 0; + + cec_write(cec, TEGRA_CEC_HW_CONTROL, 0); + cec_write(cec, TEGRA_CEC_INT_MASK, 0); + cec_write(cec, TEGRA_CEC_INT_STAT, 0xffffffff); + cec_write(cec, TEGRA_CEC_SW_CONTROL, 0); + + if (!enable) + return 0; + + cec_write(cec, TEGRA_CEC_INPUT_FILTER, (1U << 31) | 0x20); + + cec_write(cec, TEGRA_CEC_RX_TIMING_0, + (0x7a << TEGRA_CEC_RX_TIM0_START_BIT_MAX_LO_TIME_SHIFT) | + (0x6d << TEGRA_CEC_RX_TIM0_START_BIT_MIN_LO_TIME_SHIFT) | + (0x93 << TEGRA_CEC_RX_TIM0_START_BIT_MAX_DURATION_SHIFT) | + (0x86 << TEGRA_CEC_RX_TIM0_START_BIT_MIN_DURATION_SHIFT)); + + cec_write(cec, TEGRA_CEC_RX_TIMING_1, + (0x35 << TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_LO_TIME_SHIFT) | + (0x21 << TEGRA_CEC_RX_TIM1_DATA_BIT_SAMPLE_TIME_SHIFT) | + (0x56 << TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_DURATION_SHIFT) | + (0x40 << TEGRA_CEC_RX_TIM1_DATA_BIT_MIN_DURATION_SHIFT)); + + cec_write(cec, TEGRA_CEC_RX_TIMING_2, + (0x50 << TEGRA_CEC_RX_TIM2_END_OF_BLOCK_TIME_SHIFT)); + + cec_write(cec, TEGRA_CEC_TX_TIMING_0, + (0x74 << TEGRA_CEC_TX_TIM0_START_BIT_LO_TIME_SHIFT) | + (0x8d << TEGRA_CEC_TX_TIM0_START_BIT_DURATION_SHIFT) | + (0x08 << TEGRA_CEC_TX_TIM0_BUS_XITION_TIME_SHIFT) | + (0x71 << TEGRA_CEC_TX_TIM0_BUS_ERROR_LO_TIME_SHIFT)); + + cec_write(cec, TEGRA_CEC_TX_TIMING_1, + (0x2f << TEGRA_CEC_TX_TIM1_LO_DATA_BIT_LO_TIME_SHIFT) | + (0x13 << TEGRA_CEC_TX_TIM1_HI_DATA_BIT_LO_TIME_SHIFT) | + (0x4b << TEGRA_CEC_TX_TIM1_DATA_BIT_DURATION_SHIFT) | + (0x21 << TEGRA_CEC_TX_TIM1_ACK_NAK_BIT_SAMPLE_TIME_SHIFT)); + + cec_write(cec, TEGRA_CEC_TX_TIMING_2, + (0x07 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_ADDITIONAL_FRAME_SHIFT) | + (0x05 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_NEW_FRAME_SHIFT) | + (0x03 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_RETRY_FRAME_SHIFT)); + + cec_write(cec, TEGRA_CEC_INT_MASK, + TEGRA_CEC_INT_MASK_TX_REGISTER_UNDERRUN | + TEGRA_CEC_INT_MASK_TX_FRAME_OR_BLOCK_NAKD | + TEGRA_CEC_INT_MASK_TX_ARBITRATION_FAILED | + TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED | + TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED | + TEGRA_CEC_INT_MASK_RX_REGISTER_FULL | + TEGRA_CEC_INT_MASK_RX_REGISTER_OVERRUN); + + cec_write(cec, TEGRA_CEC_HW_CONTROL, TEGRA_CEC_HWCTRL_TX_RX_MODE); + return 0; +} + +static int tegra_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr) +{ + struct tegra_cec *cec = adap->priv; + u32 state = cec_read(cec, TEGRA_CEC_HW_CONTROL); + + if (logical_addr == CEC_LOG_ADDR_INVALID) + state &= ~TEGRA_CEC_HWCTRL_RX_LADDR_MASK; + else + state |= TEGRA_CEC_HWCTRL_RX_LADDR((1 << logical_addr)); + + cec_write(cec, TEGRA_CEC_HW_CONTROL, state); + return 0; +} + +static int tegra_cec_adap_monitor_all_enable(struct cec_adapter *adap, + bool enable) +{ + struct tegra_cec *cec = adap->priv; + u32 reg = cec_read(cec, TEGRA_CEC_HW_CONTROL); + + if (enable) + reg |= TEGRA_CEC_HWCTRL_RX_SNOOP; + else + reg &= ~TEGRA_CEC_HWCTRL_RX_SNOOP; + cec_write(cec, TEGRA_CEC_HW_CONTROL, reg); + return 0; +} + +static int tegra_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time_ms, struct cec_msg *msg) +{ + bool retry_xfer = signal_free_time_ms == CEC_SIGNAL_FREE_TIME_RETRY; + struct tegra_cec *cec = adap->priv; + unsigned int i; + u32 mode = 0; + u32 mask; + + if (cec_msg_is_broadcast(msg)) + mode = TEGRA_CEC_TX_REG_BCAST; + + cec->tx_buf_cur = 0; + cec->tx_buf_cnt = msg->len; + + for (i = 0; i < msg->len; i++) { + cec->tx_buf[i] = mode | msg->msg[i]; + if (i == 0) + cec->tx_buf[i] |= TEGRA_CEC_TX_REG_START_BIT; + if (i == msg->len - 1) + cec->tx_buf[i] |= TEGRA_CEC_TX_REG_EOM; + if (i == 0 && retry_xfer) + cec->tx_buf[i] |= TEGRA_CEC_TX_REG_RETRY; + } + + mask = cec_read(cec, TEGRA_CEC_INT_MASK); + cec_write(cec, TEGRA_CEC_INT_MASK, + mask | TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY); + + return 0; +} + +static const struct cec_adap_ops tegra_cec_ops = { + .adap_enable = tegra_cec_adap_enable, + .adap_log_addr = tegra_cec_adap_log_addr, + .adap_transmit = tegra_cec_adap_transmit, + .adap_monitor_all_enable = tegra_cec_adap_monitor_all_enable, +}; + +static int tegra_cec_probe(struct platform_device *pdev) +{ + struct platform_device *hdmi_dev; + struct device_node *np; + struct tegra_cec *cec; + struct resource *res; + int ret = 0; + + np = of_parse_phandle(pdev->dev.of_node, "hdmi-phandle", 0); + + if (!np) { + dev_err(&pdev->dev, "Failed to find hdmi node in device tree\n"); + return -ENODEV; + } + hdmi_dev = of_find_device_by_node(np); + if (hdmi_dev == NULL) + return -EPROBE_DEFER; + + cec = devm_kzalloc(&pdev->dev, sizeof(struct tegra_cec), GFP_KERNEL); + + if (!cec) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) { + dev_err(&pdev->dev, + "Unable to allocate resources for device\n"); + return -EBUSY; + } + + if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), + pdev->name)) { + dev_err(&pdev->dev, + "Unable to request mem region for device\n"); + return -EBUSY; + } + + cec->tegra_cec_irq = platform_get_irq(pdev, 0); + + if (cec->tegra_cec_irq <= 0) + return -EBUSY; + + cec->cec_base = devm_ioremap_nocache(&pdev->dev, res->start, + resource_size(res)); + + if (!cec->cec_base) { + dev_err(&pdev->dev, "Unable to grab IOs for device\n"); + return -EBUSY; + } + + cec->clk = devm_clk_get(&pdev->dev, "cec"); + + if (IS_ERR_OR_NULL(cec->clk)) { + dev_err(&pdev->dev, "Can't get clock for CEC\n"); + return -ENOENT; + } + + clk_prepare_enable(cec->clk); + + /* set context info. */ + cec->dev = &pdev->dev; + + platform_set_drvdata(pdev, cec); + + ret = devm_request_threaded_irq(&pdev->dev, cec->tegra_cec_irq, + tegra_cec_irq_handler, tegra_cec_irq_thread_handler, + 0, "cec_irq", &pdev->dev); + + if (ret) { + dev_err(&pdev->dev, + "Unable to request interrupt for device\n"); + goto clk_error; + } + + cec->notifier = cec_notifier_get(&hdmi_dev->dev); + if (!cec->notifier) { + ret = -ENOMEM; + goto clk_error; + } + + cec->adap = cec_allocate_adapter(&tegra_cec_ops, cec, TEGRA_CEC_NAME, + CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL, + CEC_MAX_LOG_ADDRS); + if (IS_ERR(cec->adap)) { + ret = -ENOMEM; + dev_err(&pdev->dev, "Couldn't create cec adapter\n"); + goto cec_error; + } + ret = cec_register_adapter(cec->adap, &pdev->dev); + if (ret) { + dev_err(&pdev->dev, "Couldn't register device\n"); + goto cec_error; + } + + cec_register_cec_notifier(cec->adap, cec->notifier); + + return 0; + +cec_error: + if (cec->notifier) + cec_notifier_put(cec->notifier); + cec_delete_adapter(cec->adap); +clk_error: + clk_disable_unprepare(cec->clk); + return ret; +} + +static int tegra_cec_remove(struct platform_device *pdev) +{ + struct tegra_cec *cec = platform_get_drvdata(pdev); + + clk_disable_unprepare(cec->clk); + + cec_unregister_adapter(cec->adap); + cec_notifier_put(cec->notifier); + + return 0; +} + +#ifdef CONFIG_PM +static int tegra_cec_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct tegra_cec *cec = platform_get_drvdata(pdev); + + clk_disable_unprepare(cec->clk); + + dev_notice(&pdev->dev, "suspended\n"); + return 0; +} + +static int tegra_cec_resume(struct platform_device *pdev) +{ + struct tegra_cec *cec = platform_get_drvdata(pdev); + + dev_notice(&pdev->dev, "Resuming\n"); + + clk_prepare_enable(cec->clk); + + return 0; +} +#endif + +static const struct of_device_id tegra_cec_of_match[] = { + { .compatible = "nvidia,tegra114-cec", }, + { .compatible = "nvidia,tegra124-cec", }, + { .compatible = "nvidia,tegra210-cec", }, + {}, +}; + +static struct platform_driver tegra_cec_driver = { + .driver = { + .name = TEGRA_CEC_NAME, + .of_match_table = of_match_ptr(tegra_cec_of_match), + }, + .probe = tegra_cec_probe, + .remove = tegra_cec_remove, + +#ifdef CONFIG_PM + .suspend = tegra_cec_suspend, + .resume = tegra_cec_resume, +#endif +}; + +module_platform_driver(tegra_cec_driver); diff --git a/drivers/media/platform/tegra-cec/tegra_cec.h b/drivers/media/platform/tegra-cec/tegra_cec.h new file mode 100644 index 000000000000..e301513daa87 --- /dev/null +++ b/drivers/media/platform/tegra-cec/tegra_cec.h @@ -0,0 +1,127 @@ +/* + * Tegra CEC register definitions + * + * The original 3.10 CEC driver using a custom API: + * + * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved. + * + * Conversion to the CEC framework and to the mainline kernel: + * + * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TEGRA_CEC_H +#define TEGRA_CEC_H + +/* CEC registers */ +#define TEGRA_CEC_SW_CONTROL 0x000 +#define TEGRA_CEC_HW_CONTROL 0x004 +#define TEGRA_CEC_INPUT_FILTER 0x008 +#define TEGRA_CEC_TX_REGISTER 0x010 +#define TEGRA_CEC_RX_REGISTER 0x014 +#define TEGRA_CEC_RX_TIMING_0 0x018 +#define TEGRA_CEC_RX_TIMING_1 0x01c +#define TEGRA_CEC_RX_TIMING_2 0x020 +#define TEGRA_CEC_TX_TIMING_0 0x024 +#define TEGRA_CEC_TX_TIMING_1 0x028 +#define TEGRA_CEC_TX_TIMING_2 0x02c +#define TEGRA_CEC_INT_STAT 0x030 +#define TEGRA_CEC_INT_MASK 0x034 +#define TEGRA_CEC_HW_DEBUG_RX 0x038 +#define TEGRA_CEC_HW_DEBUG_TX 0x03c + +#define TEGRA_CEC_HWCTRL_RX_LADDR_MASK 0x7fff +#define TEGRA_CEC_HWCTRL_RX_LADDR(x) \ + ((x) & TEGRA_CEC_HWCTRL_RX_LADDR_MASK) +#define TEGRA_CEC_HWCTRL_RX_SNOOP (1 << 15) +#define TEGRA_CEC_HWCTRL_RX_NAK_MODE (1 << 16) +#define TEGRA_CEC_HWCTRL_TX_NAK_MODE (1 << 24) +#define TEGRA_CEC_HWCTRL_FAST_SIM_MODE (1 << 30) +#define TEGRA_CEC_HWCTRL_TX_RX_MODE (1 << 31) + +#define TEGRA_CEC_INPUT_FILTER_MODE (1 << 31) +#define TEGRA_CEC_INPUT_FILTER_FIFO_LENGTH_SHIFT 0 + +#define TEGRA_CEC_TX_REG_DATA_SHIFT 0 +#define TEGRA_CEC_TX_REG_EOM (1 << 8) +#define TEGRA_CEC_TX_REG_BCAST (1 << 12) +#define TEGRA_CEC_TX_REG_START_BIT (1 << 16) +#define TEGRA_CEC_TX_REG_RETRY (1 << 17) + +#define TEGRA_CEC_RX_REGISTER_SHIFT 0 +#define TEGRA_CEC_RX_REGISTER_EOM (1 << 8) +#define TEGRA_CEC_RX_REGISTER_ACK (1 << 9) + +#define TEGRA_CEC_RX_TIM0_START_BIT_MAX_LO_TIME_SHIFT 0 +#define TEGRA_CEC_RX_TIM0_START_BIT_MIN_LO_TIME_SHIFT 8 +#define TEGRA_CEC_RX_TIM0_START_BIT_MAX_DURATION_SHIFT 16 +#define TEGRA_CEC_RX_TIM0_START_BIT_MIN_DURATION_SHIFT 24 + +#define TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_LO_TIME_SHIFT 0 +#define TEGRA_CEC_RX_TIM1_DATA_BIT_SAMPLE_TIME_SHIFT 8 +#define TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_DURATION_SHIFT 16 +#define TEGRA_CEC_RX_TIM1_DATA_BIT_MIN_DURATION_SHIFT 24 + +#define TEGRA_CEC_RX_TIM2_END_OF_BLOCK_TIME_SHIFT 0 + +#define TEGRA_CEC_TX_TIM0_START_BIT_LO_TIME_SHIFT 0 +#define TEGRA_CEC_TX_TIM0_START_BIT_DURATION_SHIFT 8 +#define TEGRA_CEC_TX_TIM0_BUS_XITION_TIME_SHIFT 16 +#define TEGRA_CEC_TX_TIM0_BUS_ERROR_LO_TIME_SHIFT 24 + +#define TEGRA_CEC_TX_TIM1_LO_DATA_BIT_LO_TIME_SHIFT 0 +#define TEGRA_CEC_TX_TIM1_HI_DATA_BIT_LO_TIME_SHIFT 8 +#define TEGRA_CEC_TX_TIM1_DATA_BIT_DURATION_SHIFT 16 +#define TEGRA_CEC_TX_TIM1_ACK_NAK_BIT_SAMPLE_TIME_SHIFT 24 + +#define TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_ADDITIONAL_FRAME_SHIFT 0 +#define TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_NEW_FRAME_SHIFT 4 +#define TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_RETRY_FRAME_SHIFT 8 + +#define TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY (1 << 0) +#define TEGRA_CEC_INT_STAT_TX_REGISTER_UNDERRUN (1 << 1) +#define TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD (1 << 2) +#define TEGRA_CEC_INT_STAT_TX_ARBITRATION_FAILED (1 << 3) +#define TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED (1 << 4) +#define TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED (1 << 5) +#define TEGRA_CEC_INT_STAT_RX_REGISTER_FULL (1 << 8) +#define TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN (1 << 9) +#define TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED (1 << 10) +#define TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED (1 << 11) +#define TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED (1 << 12) +#define TEGRA_CEC_INT_STAT_FILTERED_RX_DATA_PIN_TRANSITION_H2L (1 << 13) +#define TEGRA_CEC_INT_STAT_FILTERED_RX_DATA_PIN_TRANSITION_L2H (1 << 14) + +#define TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY (1 << 0) +#define TEGRA_CEC_INT_MASK_TX_REGISTER_UNDERRUN (1 << 1) +#define TEGRA_CEC_INT_MASK_TX_FRAME_OR_BLOCK_NAKD (1 << 2) +#define TEGRA_CEC_INT_MASK_TX_ARBITRATION_FAILED (1 << 3) +#define TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED (1 << 4) +#define TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED (1 << 5) +#define TEGRA_CEC_INT_MASK_RX_REGISTER_FULL (1 << 8) +#define TEGRA_CEC_INT_MASK_RX_REGISTER_OVERRUN (1 << 9) +#define TEGRA_CEC_INT_MASK_RX_START_BIT_DETECTED (1 << 10) +#define TEGRA_CEC_INT_MASK_RX_BUS_ANOMALY_DETECTED (1 << 11) +#define TEGRA_CEC_INT_MASK_RX_BUS_ERROR_DETECTED (1 << 12) +#define TEGRA_CEC_INT_MASK_FILTERED_RX_DATA_PIN_TRANSITION_H2L (1 << 13) +#define TEGRA_CEC_INT_MASK_FILTERED_RX_DATA_PIN_TRANSITION_L2H (1 << 14) + +#define TEGRA_CEC_HW_DEBUG_TX_DURATION_COUNT_SHIFT 0 +#define TEGRA_CEC_HW_DEBUG_TX_TXBIT_COUNT_SHIFT 17 +#define TEGRA_CEC_HW_DEBUG_TX_STATE_SHIFT 21 +#define TEGRA_CEC_HW_DEBUG_TX_FORCELOOUT (1 << 25) +#define TEGRA_CEC_HW_DEBUG_TX_TXDATABIT_SAMPLE_TIMER (1 << 26) + +#endif /* TEGRA_CEC_H */ diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c index 42e383a48ffe..8b586c864524 100644 --- a/drivers/media/platform/ti-vpe/cal.c +++ b/drivers/media/platform/ti-vpe/cal.c @@ -1522,6 +1522,11 @@ static int cal_async_complete(struct v4l2_async_notifier *notifier) return 0; } +static const struct v4l2_async_notifier_operations cal_async_ops = { + .bound = cal_async_bound, + .complete = cal_async_complete, +}; + static int cal_complete_ctx(struct cal_ctx *ctx) { struct video_device *vfd; @@ -1736,8 +1741,7 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) ctx->asd_list[0] = asd; ctx->notifier.subdevs = ctx->asd_list; ctx->notifier.num_subdevs = 1; - ctx->notifier.bound = cal_async_bound; - ctx->notifier.complete = cal_async_complete; + ctx->notifier.ops = &cal_async_ops; ret = v4l2_async_notifier_register(&ctx->v4l2_dev, &ctx->notifier); if (ret) { diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index 45bd10544189..e395aa85c8ad 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -926,7 +926,7 @@ static struct vpe_ctx *file2ctx(struct file *file) * mem2mem callbacks */ -/** +/* * job_ready() - check whether an instance is ready to be scheduled to run */ static int job_ready(void *priv) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index b01fba020d5f..065483e62db4 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -343,7 +343,7 @@ static void schedule_irq(struct vim2m_dev *dev, int msec_timeout) * mem2mem callbacks */ -/** +/* * job_ready() - check whether an instance is ready to be scheduled to run */ static int job_ready(void *priv) @@ -388,9 +388,9 @@ static void device_run(void *priv) schedule_irq(dev, ctx->transtime); } -static void device_isr(unsigned long priv) +static void device_isr(struct timer_list *t) { - struct vim2m_dev *vim2m_dev = (struct vim2m_dev *)priv; + struct vim2m_dev *vim2m_dev = from_timer(vim2m_dev, t, timer); struct vim2m_ctx *curr_ctx; struct vb2_v4l2_buffer *src_vb, *dst_vb; unsigned long flags; @@ -1024,7 +1024,7 @@ static int vim2m_probe(struct platform_device *pdev) v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n", vfd->num); - setup_timer(&dev->timer, device_isr, (long)dev); + timer_setup(&dev->timer, device_isr, 0); platform_set_drvdata(pdev, dev); dev->m2m_dev = v4l2_m2m_init(&m2m_ops); diff --git a/drivers/media/platform/vimc/vimc-core.c b/drivers/media/platform/vimc/vimc-core.c index 51c0eee61ca6..fe088a953860 100644 --- a/drivers/media/platform/vimc/vimc-core.c +++ b/drivers/media/platform/vimc/vimc-core.c @@ -267,11 +267,12 @@ static struct component_match *vimc_add_subdevs(struct vimc_device *vimc) PLATFORM_DEVID_AUTO, &pdata, sizeof(pdata)); - if (!vimc->subdevs[i]) { + if (IS_ERR(vimc->subdevs[i])) { + match = ERR_CAST(vimc->subdevs[i]); while (--i >= 0) platform_device_unregister(vimc->subdevs[i]); - return ERR_PTR(-ENOMEM); + return match; } component_match_add(&vimc->pdev.dev, &match, vimc_comp_compare, diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c index f0f423c7ca41..a651527d80db 100644 --- a/drivers/media/platform/vivid/vivid-vid-common.c +++ b/drivers/media/platform/vivid/vivid-vid-common.c @@ -189,6 +189,22 @@ struct vivid_fmt vivid_formats[] = { .buffers = 1, }, { + .fourcc = V4L2_PIX_FMT_Y10, + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .color_enc = TGP_COLOR_ENC_LUMA, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_Y12, + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .color_enc = TGP_COLOR_ENC_LUMA, + .planes = 1, + .buffers = 1, + }, + { .fourcc = V4L2_PIX_FMT_Y16, .vdownsampling = { 1 }, .bit_depth = { 16 }, diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 8b5cbb6b7a70..4257451f1bd8 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -70,6 +70,7 @@ struct vsp1_dl_body { * @dma: DMA address for the header * @body0: first display list body * @fragments: list of extra display list bodies + * @has_chain: if true, indicates that there's a partition chain * @chain: entry in the display list partition chain */ struct vsp1_dl_list { diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index ebfdf334d99c..d881cf09876d 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -351,6 +351,11 @@ static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier, return -EINVAL; } +static const struct v4l2_async_notifier_operations xvip_graph_notify_ops = { + .bound = xvip_graph_notify_bound, + .complete = xvip_graph_notify_complete, +}; + static int xvip_graph_parse_one(struct xvip_composite_device *xdev, struct device_node *node) { @@ -548,8 +553,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev) xdev->notifier.subdevs = subdevs; xdev->notifier.num_subdevs = num_subdevs; - xdev->notifier.bound = xvip_graph_notify_bound; - xdev->notifier.complete = xvip_graph_notify_complete; + xdev->notifier.ops = &xvip_graph_notify_ops; ret = v4l2_async_notifier_register(&xdev->v4l2_dev, &xdev->notifier); if (ret < 0) { diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 6888b7db449d..7575e5370a49 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -281,9 +281,9 @@ static bool cadet_has_rds_data(struct cadet *dev) } -static void cadet_handler(unsigned long data) +static void cadet_handler(struct timer_list *t) { - struct cadet *dev = (void *)data; + struct cadet *dev = from_timer(dev, t, readtimer); /* Service the RDS fifo */ if (mutex_trylock(&dev->lock)) { @@ -309,7 +309,6 @@ static void cadet_handler(unsigned long data) /* * Clean up and exit */ - setup_timer(&dev->readtimer, cadet_handler, data); dev->readtimer.expires = jiffies + msecs_to_jiffies(50); add_timer(&dev->readtimer); } @@ -318,7 +317,7 @@ static void cadet_start_rds(struct cadet *dev) { dev->rdsstat = 1; outb(0x80, dev->io); /* Select RDS fifo */ - setup_timer(&dev->readtimer, cadet_handler, (unsigned long)dev); + timer_setup(&dev->readtimer, cadet_handler, 0); dev->readtimer.expires = jiffies + msecs_to_jiffies(50); add_timer(&dev->readtimer); } diff --git a/drivers/media/radio/radio-raremono.c b/drivers/media/radio/radio-raremono.c index 3c0a22a54113..70a2c86774ce 100644 --- a/drivers/media/radio/radio-raremono.c +++ b/drivers/media/radio/radio-raremono.c @@ -254,7 +254,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { struct raremono_device *radio = video_drvdata(file); - u32 freq = f->frequency; + u32 freq; unsigned band; if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 271f725b17e8..540ac887a63c 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -158,7 +158,7 @@ enum si476x_ctrl_idx { }; static struct v4l2_ctrl_config si476x_ctrls[] = { - /** + /* * SI476X during its station seeking(or tuning) process uses several * parameters to detrmine if "the station" is valid: * @@ -197,7 +197,7 @@ static struct v4l2_ctrl_config si476x_ctrls[] = { .step = 2, }, - /** + /* * #V4L2_CID_SI476X_HARMONICS_COUNT -- number of harmonics * built-in power-line noise supression filter is to reject * during AM-mode operation. @@ -213,7 +213,7 @@ static struct v4l2_ctrl_config si476x_ctrls[] = { .step = 1, }, - /** + /* * #V4L2_CID_SI476X_DIVERSITY_MODE -- configuration which * two tuners working in diversity mode are to work in. * @@ -237,7 +237,7 @@ static struct v4l2_ctrl_config si476x_ctrls[] = { .max = ARRAY_SIZE(phase_diversity_modes) - 1, }, - /** + /* * #V4L2_CID_SI476X_INTERCHIP_LINK -- inter-chip link in * diversity mode indicator. Allows user to determine if two * chips working in diversity mode have established a link @@ -296,11 +296,15 @@ struct si476x_radio_ops { /** * struct si476x_radio - radio device * - * @core: Pointer to underlying core device + * @v4l2dev: Pointer to V4L2 device created by V4L2 subsystem * @videodev: Pointer to video device created by V4L2 subsystem + * @ctrl_handler: V4L2 controls handler + * @core: Pointer to underlying core device * @ops: Vtable of functions. See struct si476x_radio_ops for details - * @kref: Reference counter - * @core_lock: An r/w semaphore to brebvent the deletion of underlying + * @debugfs: pointer to &strucd dentry for debugfs + * @audmode: audio mode, as defined for the rxsubchans field + * at videodev2.h + * * core structure is the radio device is being used */ struct si476x_radio { diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index 903fcd5e99c0..3cbdc085c65d 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -1330,7 +1330,7 @@ static int wl1273_fm_vidioc_s_input(struct file *file, void *priv, /** * wl1273_fm_set_tx_power() - Set the transmission power value. - * @core: A pointer to the device struct. + * @radio: A pointer to the device struct. * @power: The new power value. */ static int wl1273_fm_set_tx_power(struct wl1273_device *radio, u16 power) diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index cd76facc22f5..c89a7d5b8c55 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -749,7 +749,7 @@ static const struct v4l2_ioctl_ops si470x_ioctl_ops = { /* * si470x_viddev_template - video device interface */ -struct video_device si470x_viddev_template = { +const struct video_device si470x_viddev_template = { .fops = &si470x_fops, .name = DRIVER_NAME, .release = video_device_release_empty, diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index 7d2defd9d399..eb7b834a0ae5 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h @@ -209,7 +209,7 @@ struct si470x_device { /************************************************************************** * Common Functions **************************************************************************/ -extern struct video_device si470x_viddev_template; +extern const struct video_device si470x_viddev_template; extern const struct v4l2_ctrl_ops si470x_ctrl_ops; int si470x_get_register(struct si470x_device *radio, int regnr); int si470x_set_register(struct si470x_device *radio, int regnr); diff --git a/drivers/media/radio/wl128x/Kconfig b/drivers/media/radio/wl128x/Kconfig index c9e349b169c4..2add222ea346 100644 --- a/drivers/media/radio/wl128x/Kconfig +++ b/drivers/media/radio/wl128x/Kconfig @@ -7,11 +7,11 @@ config RADIO_WL128X depends on VIDEO_V4L2 && RFKILL && TTY && TI_ST depends on GPIOLIB || COMPILE_TEST help - Choose Y here if you have this FM radio chip. + Choose Y here if you have this FM radio chip. - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux 2 API. Information on - this API and pointers to "v4l2" programs may be found at - <file:Documentation/video4linux/API.html>. + In order to control your radio card, you will need to use programs + that are compatible with the Video For Linux 2 API. Information on + this API and pointers to "v4l2" programs may be found at + <file:Documentation/video4linux/API.html>. endmenu diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index ab3428bf63fe..800d69c3f80b 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -543,13 +543,13 @@ static inline void fm_irq_common_cmd_resp_helper(struct fmdev *fmdev, u8 stage) * interrupt process. Therefore reset stage index to re-enable default * interrupts. So that next interrupt will be processed as usual. */ -static void int_timeout_handler(unsigned long data) +static void int_timeout_handler(struct timer_list *t) { struct fmdev *fmdev; struct fm_irq *fmirq; fmdbg("irq: timeout,trying to re-enable fm interrupts\n"); - fmdev = (struct fmdev *)data; + fmdev = from_timer(fmdev, t, irq_info.timer); fmirq = &fmdev->irq_info; fmirq->retry++; @@ -1550,8 +1550,7 @@ int fmc_prepare(struct fmdev *fmdev) atomic_set(&fmdev->tx_cnt, 1); fmdev->resp_comp = NULL; - setup_timer(&fmdev->irq_info.timer, &int_timeout_handler, - (unsigned long)fmdev); + timer_setup(&fmdev->irq_info.timer, int_timeout_handler, 0); /*TODO: add FM_STIC_EVENT later */ fmdev->irq_info.mask = FM_MAL_EVENT; diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index d9ce8ff55d0c..afb3456d4e20 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -2,7 +2,6 @@ menuconfig RC_CORE tristate "Remote Controller support" depends on INPUT - default y ---help--- Enable support for Remote Controllers on Linux. This is needed in order to support several video capture adapters, @@ -179,6 +178,7 @@ config IR_ENE config IR_HIX5HD2 tristate "Hisilicon hix5hd2 IR remote control" depends on RC_CORE + depends on OF || COMPILE_TEST help Say Y here if you want to use hisilicon hix5hd2 remote control. To compile this driver as a module, choose M here: the module will be @@ -286,6 +286,7 @@ config IR_REDRAT3 config IR_SPI tristate "SPI connected IR LED" depends on SPI && LIRC + depends on OF || COMPILE_TEST ---help--- Say Y if you want to use an IR LED connected through SPI bus. @@ -393,6 +394,7 @@ config RC_LOOPBACK config IR_GPIO_CIR tristate "GPIO IR remote control" depends on RC_CORE + depends on (OF && GPIOLIB) || COMPILE_TEST ---help--- Say Y if you want to use GPIO based IR Receiver. @@ -403,6 +405,7 @@ config IR_GPIO_TX tristate "GPIO IR Bit Banging Transmitter" depends on RC_CORE depends on LIRC + depends on (OF && GPIOLIB) || COMPILE_TEST ---help--- Say Y if you want to a GPIO based IR transmitter. This is a bit banging driver. @@ -415,6 +418,7 @@ config IR_PWM_TX depends on RC_CORE depends on LIRC depends on PWM + depends on OF || COMPILE_TEST ---help--- Say Y if you want to use a PWM based IR transmitter. This is more power efficient than the bit banging gpio driver. @@ -469,6 +473,16 @@ config IR_SIR To compile this driver as a module, choose M here: the module will be called sir-ir. +config IR_TANGO + tristate "Sigma Designs SMP86xx IR decoder" + depends on RC_CORE + depends on ARCH_TANGO || COMPILE_TEST + ---help--- + Adds support for the HW IR decoder embedded on Sigma Designs + Tango-based systems (SMP86xx, SMP87xx). + The HW decoder supports NEC, RC-5, RC-6 IR protocols. + When compiled as a module, look for tango-ir. + config IR_ZX tristate "ZTE ZX IR remote control" depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index ab3d5a135453..10026477a677 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -45,3 +45,4 @@ obj-$(CONFIG_IR_SERIAL) += serial_ir.o obj-$(CONFIG_IR_SIR) += sir_ir.o obj-$(CONFIG_IR_MTK) += mtk-cir.o obj-$(CONFIG_IR_ZX) += zx-irdec.o +obj-$(CONFIG_IR_TANGO) += tango-ir.o diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c index d0871d60a723..8e82610ffaad 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c @@ -198,7 +198,7 @@ static const struct ati_receiver_type type_firefly = { .default_keymap = RC_MAP_SNAPSTREAM_FIREFLY }; -static struct usb_device_id ati_remote_table[] = { +static const struct usb_device_id ati_remote_table[] = { { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index af7ba23e16e1..71b8c9bbf6c4 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -670,9 +670,9 @@ exit: } /* timer to simulate tx done interrupt */ -static void ene_tx_irqsim(unsigned long data) +static void ene_tx_irqsim(struct timer_list *t) { - struct ene_device *dev = (struct ene_device *)data; + struct ene_device *dev = from_timer(dev, t, tx_sim_timer); unsigned long flags; spin_lock_irqsave(&dev->hw_lock, flags); @@ -1045,8 +1045,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) if (!dev->hw_learning_and_tx_capable && txsim) { dev->hw_learning_and_tx_capable = true; - setup_timer(&dev->tx_sim_timer, ene_tx_irqsim, - (long unsigned int)dev); + timer_setup(&dev->tx_sim_timer, ene_tx_irqsim, 0); pr_warn("Simulation of TX activated\n"); } diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 7248b3662285..3d99b51384ac 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -14,119 +14,64 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/slab.h> #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/platform_device.h> #include <linux/irq.h> #include <media/rc-core.h> -#include <linux/platform_data/media/gpio-ir-recv.h> -#define GPIO_IR_DRIVER_NAME "gpio-rc-recv" #define GPIO_IR_DEVICE_NAME "gpio_ir_recv" struct gpio_rc_dev { struct rc_dev *rcdev; - int gpio_nr; - bool active_low; + struct gpio_desc *gpiod; + int irq; }; -#ifdef CONFIG_OF -/* - * Translate OpenFirmware node properties into platform_data - */ -static int gpio_ir_recv_get_devtree_pdata(struct device *dev, - struct gpio_ir_recv_platform_data *pdata) -{ - struct device_node *np = dev->of_node; - enum of_gpio_flags flags; - int gpio; - - gpio = of_get_gpio_flags(np, 0, &flags); - if (gpio < 0) { - if (gpio != -EPROBE_DEFER) - dev_err(dev, "Failed to get gpio flags (%d)\n", gpio); - return gpio; - } - - pdata->gpio_nr = gpio; - pdata->active_low = (flags & OF_GPIO_ACTIVE_LOW); - /* probe() takes care of map_name == NULL or allowed_protos == 0 */ - pdata->map_name = of_get_property(np, "linux,rc-map-name", NULL); - pdata->allowed_protos = 0; - - return 0; -} - -static const struct of_device_id gpio_ir_recv_of_match[] = { - { .compatible = "gpio-ir-receiver", }, - { }, -}; -MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match); - -#else /* !CONFIG_OF */ - -#define gpio_ir_recv_get_devtree_pdata(dev, pdata) (-ENOSYS) - -#endif - static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) { + int val; struct gpio_rc_dev *gpio_dev = dev_id; - int gval; - int rc = 0; - - gval = gpio_get_value(gpio_dev->gpio_nr); - - if (gval < 0) - goto err_get_value; - - if (gpio_dev->active_low) - gval = !gval; - rc = ir_raw_event_store_edge(gpio_dev->rcdev, gval == 1); - if (rc < 0) - goto err_get_value; + val = gpiod_get_value(gpio_dev->gpiod); + if (val >= 0) + ir_raw_event_store_edge(gpio_dev->rcdev, val == 1); -err_get_value: return IRQ_HANDLED; } static int gpio_ir_recv_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct gpio_rc_dev *gpio_dev; struct rc_dev *rcdev; - const struct gpio_ir_recv_platform_data *pdata = - pdev->dev.platform_data; int rc; - if (pdev->dev.of_node) { - struct gpio_ir_recv_platform_data *dtpdata = - devm_kzalloc(&pdev->dev, sizeof(*dtpdata), GFP_KERNEL); - if (!dtpdata) - return -ENOMEM; - rc = gpio_ir_recv_get_devtree_pdata(&pdev->dev, dtpdata); - if (rc) - return rc; - pdata = dtpdata; - } - - if (!pdata) - return -EINVAL; + if (!np) + return -ENODEV; - if (pdata->gpio_nr < 0) - return -EINVAL; - - gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL); + gpio_dev = devm_kzalloc(dev, sizeof(*gpio_dev), GFP_KERNEL); if (!gpio_dev) return -ENOMEM; - rcdev = rc_allocate_device(RC_DRIVER_IR_RAW); - if (!rcdev) { - rc = -ENOMEM; - goto err_allocate_device; + gpio_dev->gpiod = devm_gpiod_get(dev, NULL, GPIOD_IN); + if (IS_ERR(gpio_dev->gpiod)) { + rc = PTR_ERR(gpio_dev->gpiod); + /* Just try again if this happens */ + if (rc != -EPROBE_DEFER) + dev_err(dev, "error getting gpio (%d)\n", rc); + return rc; } + gpio_dev->irq = gpiod_to_irq(gpio_dev->gpiod); + if (gpio_dev->irq < 0) + return gpio_dev->irq; + + rcdev = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW); + if (!rcdev) + return -ENOMEM; rcdev->priv = gpio_dev; rcdev->device_name = GPIO_IR_DEVICE_NAME; @@ -135,92 +80,52 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) rcdev->input_id.vendor = 0x0001; rcdev->input_id.product = 0x0001; rcdev->input_id.version = 0x0100; - rcdev->dev.parent = &pdev->dev; - rcdev->driver_name = GPIO_IR_DRIVER_NAME; + rcdev->dev.parent = dev; + rcdev->driver_name = KBUILD_MODNAME; rcdev->min_timeout = 1; rcdev->timeout = IR_DEFAULT_TIMEOUT; rcdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT; - if (pdata->allowed_protos) - rcdev->allowed_protocols = pdata->allowed_protos; - else - rcdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; - rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY; + rcdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; + rcdev->map_name = of_get_property(np, "linux,rc-map-name", NULL); + if (!rcdev->map_name) + rcdev->map_name = RC_MAP_EMPTY; gpio_dev->rcdev = rcdev; - gpio_dev->gpio_nr = pdata->gpio_nr; - gpio_dev->active_low = pdata->active_low; - - rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv"); - if (rc < 0) - goto err_gpio_request; - rc = gpio_direction_input(pdata->gpio_nr); - if (rc < 0) - goto err_gpio_direction_input; - rc = rc_register_device(rcdev); + rc = devm_rc_register_device(dev, rcdev); if (rc < 0) { - dev_err(&pdev->dev, "failed to register rc device\n"); - goto err_register_rc_device; + dev_err(dev, "failed to register rc device (%d)\n", rc); + return rc; } platform_set_drvdata(pdev, gpio_dev); - rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr), - gpio_ir_recv_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "gpio-ir-recv-irq", gpio_dev); - if (rc < 0) - goto err_request_irq; - - return 0; - -err_request_irq: - rc_unregister_device(rcdev); - rcdev = NULL; -err_register_rc_device: -err_gpio_direction_input: - gpio_free(pdata->gpio_nr); -err_gpio_request: - rc_free_device(rcdev); -err_allocate_device: - kfree(gpio_dev); - return rc; -} - -static int gpio_ir_recv_remove(struct platform_device *pdev) -{ - struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); - - free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); - rc_unregister_device(gpio_dev->rcdev); - gpio_free(gpio_dev->gpio_nr); - kfree(gpio_dev); - return 0; + return devm_request_irq(dev, gpio_dev->irq, gpio_ir_recv_irq, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "gpio-ir-recv-irq", gpio_dev); } #ifdef CONFIG_PM static int gpio_ir_recv_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); + struct gpio_rc_dev *gpio_dev = dev_get_drvdata(dev); if (device_may_wakeup(dev)) - enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); + enable_irq_wake(gpio_dev->irq); else - disable_irq(gpio_to_irq(gpio_dev->gpio_nr)); + disable_irq(gpio_dev->irq); return 0; } static int gpio_ir_recv_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); + struct gpio_rc_dev *gpio_dev = dev_get_drvdata(dev); if (device_may_wakeup(dev)) - disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); + disable_irq_wake(gpio_dev->irq); else - enable_irq(gpio_to_irq(gpio_dev->gpio_nr)); + enable_irq(gpio_dev->irq); return 0; } @@ -231,11 +136,16 @@ static const struct dev_pm_ops gpio_ir_recv_pm_ops = { }; #endif +static const struct of_device_id gpio_ir_recv_of_match[] = { + { .compatible = "gpio-ir-receiver", }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match); + static struct platform_driver gpio_ir_recv_driver = { .probe = gpio_ir_recv_probe, - .remove = gpio_ir_recv_remove, .driver = { - .name = GPIO_IR_DRIVER_NAME, + .name = KBUILD_MODNAME, .of_match_table = of_match_ptr(gpio_ir_recv_of_match), #ifdef CONFIG_PM .pm = &gpio_ir_recv_pm_ops, diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c index a5ea86be8f44..f563ddd7f739 100644 --- a/drivers/media/rc/igorplugusb.c +++ b/drivers/media/rc/igorplugusb.c @@ -137,9 +137,9 @@ static void igorplugusb_cmd(struct igorplugusb *ir, int cmd) dev_err(ir->dev, "submit urb failed: %d", ret); } -static void igorplugusb_timer(unsigned long data) +static void igorplugusb_timer(struct timer_list *t) { - struct igorplugusb *ir = (struct igorplugusb *)data; + struct igorplugusb *ir = from_timer(ir, t, timer); igorplugusb_cmd(ir, GET_INFRACODE); } @@ -174,7 +174,7 @@ static int igorplugusb_probe(struct usb_interface *intf, ir->dev = &intf->dev; - setup_timer(&ir->timer, igorplugusb_timer, (unsigned long)ir); + timer_setup(&ir->timer, igorplugusb_timer, 0); ir->request.bRequest = GET_INFRACODE; ir->request.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN; @@ -245,7 +245,7 @@ static void igorplugusb_disconnect(struct usb_interface *intf) usb_free_urb(ir->urb); } -static struct usb_device_id igorplugusb_table[] = { +static const struct usb_device_id igorplugusb_table[] = { /* Igor Plug USB (Atmel's Manufact. ID) */ { USB_DEVICE(0x03eb, 0x0002) }, /* Fit PC2 Infrared Adapter */ diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c index 03fe080278df..bcbabeeab12a 100644 --- a/drivers/media/rc/img-ir/img-ir-core.c +++ b/drivers/media/rc/img-ir/img-ir-core.c @@ -92,10 +92,9 @@ static int img_ir_probe(struct platform_device *pdev) /* Private driver data */ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "cannot allocate device data\n"); + if (!priv) return -ENOMEM; - } + platform_set_drvdata(pdev, priv); priv->dev = &pdev->dev; spin_lock_init(&priv->lock); diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 82fdf4cc0824..ec4ded84cd17 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -339,7 +339,7 @@ static void img_ir_decoder_preprocess(struct img_ir_decoder *decoder) /** * img_ir_decoder_convert() - Generate internal timings in decoder. * @decoder: Decoder to be converted to internal timings. - * @timings: Timing register values. + * @reg_timings: Timing register values. * @clock_hz: IR clock rate in Hz. * * Fills out the repeat timings and timing register values for a specific clock @@ -867,9 +867,9 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) } /* timer function to end waiting for repeat. */ -static void img_ir_end_timer(unsigned long arg) +static void img_ir_end_timer(struct timer_list *t) { - struct img_ir_priv *priv = (struct img_ir_priv *)arg; + struct img_ir_priv *priv = from_timer(priv, t, hw.end_timer); spin_lock_irq(&priv->lock); img_ir_end_repeat(priv); @@ -881,9 +881,9 @@ static void img_ir_end_timer(unsigned long arg) * cleared when invalid interrupts were generated due to a quirk in the * img-ir decoder. */ -static void img_ir_suspend_timer(unsigned long arg) +static void img_ir_suspend_timer(struct timer_list *t) { - struct img_ir_priv *priv = (struct img_ir_priv *)arg; + struct img_ir_priv *priv = from_timer(priv, t, hw.suspend_timer); spin_lock_irq(&priv->lock); /* @@ -1055,9 +1055,8 @@ int img_ir_probe_hw(struct img_ir_priv *priv) img_ir_probe_hw_caps(priv); /* Set up the end timer */ - setup_timer(&hw->end_timer, img_ir_end_timer, (unsigned long)priv); - setup_timer(&hw->suspend_timer, img_ir_suspend_timer, - (unsigned long)priv); + timer_setup(&hw->end_timer, img_ir_end_timer, 0); + timer_setup(&hw->suspend_timer, img_ir_suspend_timer, 0); /* Register a clock notifier */ if (!IS_ERR(priv->clk)) { diff --git a/drivers/media/rc/img-ir/img-ir-raw.c b/drivers/media/rc/img-ir/img-ir-raw.c index 64714efc1145..6e545680d3b6 100644 --- a/drivers/media/rc/img-ir/img-ir-raw.c +++ b/drivers/media/rc/img-ir/img-ir-raw.c @@ -67,9 +67,9 @@ void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status) * order to be assured of the final space. If there are no edges for a certain * time we use this timer to emit a final sample to satisfy them. */ -static void img_ir_echo_timer(unsigned long arg) +static void img_ir_echo_timer(struct timer_list *t) { - struct img_ir_priv *priv = (struct img_ir_priv *)arg; + struct img_ir_priv *priv = from_timer(priv, t, raw.timer); spin_lock_irq(&priv->lock); @@ -107,7 +107,7 @@ int img_ir_probe_raw(struct img_ir_priv *priv) int error; /* Set up the echo timer */ - setup_timer(&raw->timer, img_ir_echo_timer, (unsigned long)priv); + timer_setup(&raw->timer, img_ir_echo_timer, 0); /* Allocate raw decoder */ raw->rdev = rdev = rc_allocate_device(RC_DRIVER_IR_RAW); diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 7b3f31cc63d2..eb943e862515 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -346,7 +346,7 @@ static const struct imon_usb_dev_descr imon_ir_raw = { * devices use the SoundGraph vendor ID (0x15c2). This driver only supports * the ffdc and later devices, which do onboard decoding. */ -static struct usb_device_id imon_usb_id_table[] = { +static const struct usb_device_id imon_usb_id_table[] = { /* * Several devices with this same device ID, all use iMON_PAD.inf * SoundGraph iMON PAD (IR & VFD) @@ -492,7 +492,7 @@ static void free_imon_context(struct imon_context *ictx) dev_dbg(dev, "%s: iMON context freed\n", __func__); } -/** +/* * Called when the Display device (e.g. /dev/lcd0) * is opened by the application. */ @@ -542,7 +542,7 @@ exit: return retval; } -/** +/* * Called when the display device (e.g. /dev/lcd0) * is closed by the application. */ @@ -575,7 +575,7 @@ static int display_close(struct inode *inode, struct file *file) return retval; } -/** +/* * Sends a packet to the device -- this function must be called with * ictx->lock held, or its unlock/lock sequence while waiting for tx * to complete can/will lead to a deadlock. @@ -602,8 +602,7 @@ static int send_packet(struct imon_context *ictx) ictx->tx_urb->actual_length = 0; } else { /* fill request into kmalloc'ed space: */ - control_req = kmalloc(sizeof(struct usb_ctrlrequest), - GFP_KERNEL); + control_req = kmalloc(sizeof(*control_req), GFP_KERNEL); if (control_req == NULL) return -ENOMEM; @@ -665,7 +664,7 @@ static int send_packet(struct imon_context *ictx) return retval; } -/** +/* * Sends an associate packet to the iMON 2.4G. * * This might not be such a good idea, since it has an id collision with @@ -695,7 +694,7 @@ static int send_associate_24g(struct imon_context *ictx) return retval; } -/** +/* * Sends packets to setup and show clock on iMON display * * Arguments: year - last 2 digits of year, month - 1..12, @@ -782,7 +781,7 @@ static int send_set_imon_clock(struct imon_context *ictx, return retval; } -/** +/* * These are the sysfs functions to handle the association on the iMON 2.4G LT. */ static ssize_t show_associate_remote(struct device *d, @@ -824,7 +823,7 @@ static ssize_t store_associate_remote(struct device *d, return count; } -/** +/* * sysfs functions to control internal imon clock */ static ssize_t show_imon_clock(struct device *d, @@ -924,7 +923,7 @@ static const struct attribute_group imon_rf_attr_group = { .attrs = imon_rf_sysfs_entries }; -/** +/* * Writes data to the VFD. The iMON VFD is 2x16 characters * and requires data in 5 consecutive USB interrupt packets, * each packet but the last carrying 7 bytes. @@ -943,7 +942,7 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, int seq; int retval = 0; struct imon_context *ictx; - const unsigned char vfd_packet6[] = { + static const unsigned char vfd_packet6[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; ictx = file->private_data; @@ -1009,7 +1008,7 @@ exit: return (!retval) ? n_bytes : retval; } -/** +/* * Writes data to the LCD. The iMON OEM LCD screen expects 8-byte * packets. We accept data as 16 hexadecimal digits, followed by a * newline (to make it easy to drive the device from a command-line @@ -1067,7 +1066,7 @@ exit: return (!retval) ? n_bytes : retval; } -/** +/* * Callback function for USB core API: transmit data */ static void usb_tx_callback(struct urb *urb) @@ -1088,12 +1087,12 @@ static void usb_tx_callback(struct urb *urb) complete(&ictx->tx.finished); } -/** +/* * report touchscreen input */ -static void imon_touch_display_timeout(unsigned long data) +static void imon_touch_display_timeout(struct timer_list *t) { - struct imon_context *ictx = (struct imon_context *)data; + struct imon_context *ictx = from_timer(ictx, t, ttimer); if (ictx->display_type != IMON_DISPLAY_TYPE_VGA) return; @@ -1104,7 +1103,7 @@ static void imon_touch_display_timeout(unsigned long data) input_sync(ictx->touch); } -/** +/* * iMON IR receivers support two different signal sets -- those used by * the iMON remotes, and those used by the Windows MCE remotes (which is * really just RC-6), but only one or the other at a time, as the signals @@ -1192,7 +1191,7 @@ static inline int tv2int(const struct timeval *a, const struct timeval *b) return sec; } -/** +/* * The directional pad behaves a bit differently, depending on whether this is * one of the older ffdc devices or a newer device. Newer devices appear to * have a higher resolution matrix for more precise mouse movement, but it @@ -1544,7 +1543,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) } } -/** +/* * figure out if these is a press or a release. We don't actually * care about repeats, as those will be auto-generated within the IR * subsystem for repeating scancodes. @@ -1593,10 +1592,10 @@ static int imon_parse_press_type(struct imon_context *ictx, return press_type; } -/** +/* * Process the incoming packet */ -/** +/* * Convert bit count to time duration (in us) and submit * the value to lirc_dev. */ @@ -1609,7 +1608,7 @@ static void submit_data(struct imon_context *context) ir_raw_event_store_with_filter(context->rdev, &ev); } -/** +/* * Process the incoming packet */ static void imon_incoming_ir_raw(struct imon_context *context, @@ -1832,7 +1831,7 @@ not_input_data: } } -/** +/* * Callback function for USB core API: receive data */ static void usb_rx_callback_intf0(struct urb *urb) @@ -2047,8 +2046,8 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx) { struct rc_dev *rdev; int ret; - const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x88 }; + static const unsigned char fp_packet[] = { + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88 }; rdev = rc_allocate_device(ictx->dev_descr->flags & IMON_IR_RAW ? RC_DRIVER_IR_RAW : RC_DRIVER_SCANCODE); @@ -2310,11 +2309,10 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf, struct usb_host_interface *iface_desc; int ret = -ENOMEM; - ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL); - if (!ictx) { - dev_err(dev, "%s: kzalloc failed for context", __func__); + ictx = kzalloc(sizeof(*ictx), GFP_KERNEL); + if (!ictx) goto exit; - } + rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!rx_urb) goto rx_urb_alloc_failed; @@ -2413,8 +2411,7 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf, mutex_lock(&ictx->lock); if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { - setup_timer(&ictx->ttimer, imon_touch_display_timeout, - (unsigned long)ictx); + timer_setup(&ictx->ttimer, imon_touch_display_timeout, 0); } ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf)); @@ -2488,7 +2485,7 @@ static void imon_init_display(struct imon_context *ictx, } -/** +/* * Callback function for USB core API: Probe */ static int imon_probe(struct usb_interface *interface, @@ -2517,6 +2514,11 @@ static int imon_probe(struct usb_interface *interface, mutex_lock(&driver_lock); first_if = usb_ifnum_to_if(usbdev, 0); + if (!first_if) { + ret = -ENODEV; + goto fail; + } + first_if_ctx = usb_get_intfdata(first_if); if (ifnum == 0) { @@ -2581,7 +2583,7 @@ fail: return ret; } -/** +/* * Callback function for USB core API: disconnect */ static void imon_disconnect(struct usb_interface *interface) diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c index e2bd68c42edf..22c8aee3df4f 100644 --- a/drivers/media/rc/ir-jvc-decoder.c +++ b/drivers/media/rc/ir-jvc-decoder.c @@ -39,7 +39,7 @@ enum jvc_state { /** * ir_jvc_decode() - Decode one JVC pulse or space * @dev: the struct rc_dev descriptor of the device - * @duration: the struct ir_raw_event descriptor of the pulse/space + * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index d2223c04e9ad..4fd4521693d9 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -25,8 +25,8 @@ /** * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the * lircd userspace daemon for decoding. - * @input_dev: the struct rc_dev descriptor of the device - * @duration: the struct ir_raw_event descriptor of the pulse/space + * @dev: the struct rc_dev descriptor of the device + * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the lirc interfaces aren't wired up. */ @@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) struct lirc_codec *lirc = &dev->raw->lirc; int sample; - if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf) + if (!dev->raw->lirc.ldev || !dev->raw->lirc.ldev->buf) return -EINVAL; /* Packet start */ @@ -84,8 +84,8 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) (u64)LIRC_VALUE_MASK); gap_sample = LIRC_SPACE(lirc->gap_duration); - lirc_buffer_write(dev->raw->lirc.drv->rbuf, - (unsigned char *) &gap_sample); + lirc_buffer_write(dev->raw->lirc.ldev->buf, + (unsigned char *)&gap_sample); lirc->gap = false; } @@ -95,9 +95,9 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) TO_US(ev.duration), TO_STR(ev.pulse)); } - lirc_buffer_write(dev->raw->lirc.drv->rbuf, + lirc_buffer_write(dev->raw->lirc.ldev->buf, (unsigned char *) &sample); - wake_up(&dev->raw->lirc.drv->rbuf->wait_poll); + wake_up(&dev->raw->lirc.ldev->buf->wait_poll); return 0; } @@ -298,11 +298,14 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, if (!dev->max_timeout) return -ENOTTY; + /* Check for multiply overflow */ + if (val > U32_MAX / 1000) + return -EINVAL; + tmp = val * 1000; - if (tmp < dev->min_timeout || - tmp > dev->max_timeout) - return -EINVAL; + if (tmp < dev->min_timeout || tmp > dev->max_timeout) + return -EINVAL; if (dev->s_timeout) ret = dev->s_timeout(dev, tmp); @@ -343,12 +346,12 @@ static const struct file_operations lirc_fops = { static int ir_lirc_register(struct rc_dev *dev) { - struct lirc_driver *drv; + struct lirc_dev *ldev; int rc = -ENOMEM; unsigned long features = 0; - drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); - if (!drv) + ldev = lirc_allocate_device(); + if (!ldev) return rc; if (dev->driver_type != RC_DRIVER_IR_RAW_TX) { @@ -380,32 +383,29 @@ static int ir_lirc_register(struct rc_dev *dev) if (dev->max_timeout) features |= LIRC_CAN_SET_REC_TIMEOUT; - snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", + snprintf(ldev->name, sizeof(ldev->name), "ir-lirc-codec (%s)", dev->driver_name); - drv->minor = -1; - drv->features = features; - drv->data = &dev->raw->lirc; - drv->rbuf = NULL; - drv->code_length = sizeof(struct ir_raw_event) * 8; - drv->chunk_size = sizeof(int); - drv->buffer_size = LIRCBUF_SIZE; - drv->fops = &lirc_fops; - drv->dev = &dev->dev; - drv->rdev = dev; - drv->owner = THIS_MODULE; - - drv->minor = lirc_register_driver(drv); - if (drv->minor < 0) { - rc = -ENODEV; + ldev->features = features; + ldev->data = &dev->raw->lirc; + ldev->buf = NULL; + ldev->code_length = sizeof(struct ir_raw_event) * 8; + ldev->chunk_size = sizeof(int); + ldev->buffer_size = LIRCBUF_SIZE; + ldev->fops = &lirc_fops; + ldev->dev.parent = &dev->dev; + ldev->rdev = dev; + ldev->owner = THIS_MODULE; + + rc = lirc_register_device(ldev); + if (rc < 0) goto out; - } - dev->raw->lirc.drv = drv; + dev->raw->lirc.ldev = ldev; dev->raw->lirc.dev = dev; return 0; out: - kfree(drv); + lirc_free_device(ldev); return rc; } @@ -413,9 +413,8 @@ static int ir_lirc_unregister(struct rc_dev *dev) { struct lirc_codec *lirc = &dev->raw->lirc; - lirc_unregister_driver(lirc->drv->minor); - kfree(lirc->drv); - lirc->drv = NULL; + lirc_unregister_device(lirc->ldev); + lirc->ldev = NULL; return 0; } diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c index 7c572a643656..69d6264d54e6 100644 --- a/drivers/media/rc/ir-mce_kbd-decoder.c +++ b/drivers/media/rc/ir-mce_kbd-decoder.c @@ -115,9 +115,9 @@ static unsigned char kbd_keycodes[256] = { KEY_RESERVED }; -static void mce_kbd_rx_timeout(unsigned long data) +static void mce_kbd_rx_timeout(struct timer_list *t) { - struct mce_kbd_dec *mce_kbd = (struct mce_kbd_dec *)data; + struct mce_kbd_dec *mce_kbd = from_timer(mce_kbd, t, rx_timeout); int i; unsigned char maskcode; @@ -389,8 +389,7 @@ static int ir_mce_kbd_register(struct rc_dev *dev) set_bit(EV_MSC, idev->evbit); set_bit(MSC_SCAN, idev->mscbit); - setup_timer(&mce_kbd->rx_timeout, mce_kbd_rx_timeout, - (unsigned long)mce_kbd); + timer_setup(&mce_kbd->rx_timeout, mce_kbd_rx_timeout, 0); input_set_drvdata(idev, mce_kbd); diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c index 817c18f2ddd1..6880c190dcd2 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -41,7 +41,7 @@ enum nec_state { /** * ir_nec_decode() - Decode one NEC pulse or space * @dev: the struct rc_dev descriptor of the device - * @duration: the struct ir_raw_event descriptor of the pulse/space + * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ @@ -87,8 +87,6 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) data->state = STATE_BIT_PULSE; return 0; } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { - rc_repeat(dev); - IR_dprintk(1, "Repeat last key\n"); data->state = STATE_TRAILER_PULSE; return 0; } @@ -151,19 +149,26 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) break; - address = bitrev8((data->bits >> 24) & 0xff); - not_address = bitrev8((data->bits >> 16) & 0xff); - command = bitrev8((data->bits >> 8) & 0xff); - not_command = bitrev8((data->bits >> 0) & 0xff); + if (data->count == NEC_NBITS) { + address = bitrev8((data->bits >> 24) & 0xff); + not_address = bitrev8((data->bits >> 16) & 0xff); + command = bitrev8((data->bits >> 8) & 0xff); + not_command = bitrev8((data->bits >> 0) & 0xff); + + scancode = ir_nec_bytes_to_scancode(address, + not_address, + command, + not_command, + &rc_proto); - scancode = ir_nec_bytes_to_scancode(address, not_address, - command, not_command, - &rc_proto); + if (data->is_nec_x) + data->necx_repeat = true; - if (data->is_nec_x) - data->necx_repeat = true; + rc_keydown(dev, rc_proto, scancode, 0); + } else { + rc_repeat(dev); + } - rc_keydown(dev, rc_proto, scancode, 0); data->state = STATE_INACTIVE; return 0; } @@ -178,7 +183,6 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) * ir_nec_scancode_to_raw() - encode an NEC scancode ready for modulation. * @protocol: specific protocol to use * @scancode: a single NEC scancode. - * @raw: raw data to be modulated. */ static u32 ir_nec_scancode_to_raw(enum rc_proto protocol, u32 scancode) { diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c index 758c60956850..d94e07b02f3b 100644 --- a/drivers/media/rc/ir-sanyo-decoder.c +++ b/drivers/media/rc/ir-sanyo-decoder.c @@ -48,7 +48,7 @@ enum sanyo_state { /** * ir_sanyo_decode() - Decode one SANYO pulse or space * @dev: the struct rc_dev descriptor of the device - * @duration: the struct ir_raw_event descriptor of the pulse/space + * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c index 129b558acc92..7140dd6160ee 100644 --- a/drivers/media/rc/ir-sharp-decoder.c +++ b/drivers/media/rc/ir-sharp-decoder.c @@ -39,7 +39,7 @@ enum sharp_state { /** * ir_sharp_decode() - Decode one Sharp pulse or space * @dev: the struct rc_dev descriptor of the device - * @duration: the struct ir_raw_event descriptor of the pulse/space + * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ diff --git a/drivers/media/rc/ir-xmp-decoder.c b/drivers/media/rc/ir-xmp-decoder.c index 6f464be1c8d7..712bc6d76e92 100644 --- a/drivers/media/rc/ir-xmp-decoder.c +++ b/drivers/media/rc/ir-xmp-decoder.c @@ -35,7 +35,7 @@ enum xmp_state { /** * ir_xmp_decode() - Decode one XMP pulse or space * @dev: the struct rc_dev descriptor of the device - * @duration: the struct ir_raw_event descriptor of the pulse/space + * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 2d0b26bf2051..50b319355edf 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-alink-dtu-m.o \ rc-anysee.o \ rc-apac-viewcomp.o \ + rc-astrometa-t2hybrid.o \ rc-asus-pc39.o \ rc-asus-ps3-100.o \ rc-ati-tv-wonder-hd-600.o \ @@ -48,6 +49,8 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-geekbox.o \ rc-genius-tvgo-a11mce.o \ rc-gotview7135.o \ + rc-hisi-poplar.o \ + rc-hisi-tv-demo.o \ rc-imon-mce.o \ rc-imon-pad.o \ rc-iodata-bctv7e.o \ @@ -89,6 +92,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-reddo.o \ rc-snapstream-firefly.o \ rc-streamzap.o \ + rc-tango.o \ rc-tbs-nec.o \ rc-technisat-ts35.o \ rc-technisat-usb2.o \ diff --git a/drivers/media/rc/keymaps/rc-astrometa-t2hybrid.c b/drivers/media/rc/keymaps/rc-astrometa-t2hybrid.c new file mode 100644 index 000000000000..51690960fec4 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-astrometa-t2hybrid.c @@ -0,0 +1,70 @@ +/* + * Keytable for the Astrometa T2hybrid remote controller + * + * Copyright (C) 2017 Oleh Kravchenko <oleg@kaa.org.ua> + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <media/rc-map.h> +#include <linux/module.h> + +static struct rc_map_table t2hybrid[] = { + { 0x4d, KEY_POWER2 }, + { 0x54, KEY_VIDEO }, /* Source */ + { 0x16, KEY_MUTE }, + + { 0x4c, KEY_RECORD }, + { 0x05, KEY_CHANNELUP }, + { 0x0c, KEY_TIME}, /* Timeshift */ + + { 0x0a, KEY_VOLUMEDOWN }, + { 0x40, KEY_ZOOM }, /* Fullscreen */ + { 0x1e, KEY_VOLUMEUP }, + + { 0x12, KEY_0 }, + { 0x02, KEY_CHANNELDOWN }, + { 0x1c, KEY_AGAIN }, /* Recall */ + + { 0x09, KEY_1 }, + { 0x1d, KEY_2 }, + { 0x1f, KEY_3 }, + + { 0x0d, KEY_4 }, + { 0x19, KEY_5 }, + { 0x1b, KEY_6 }, + + { 0x11, KEY_7 }, + { 0x15, KEY_8 }, + { 0x17, KEY_9 }, +}; + +static struct rc_map_list t2hybrid_map = { + .map = { + .scan = t2hybrid, + .size = ARRAY_SIZE(t2hybrid), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_ASTROMETA_T2HYBRID, + } +}; + +static int __init init_rc_map_t2hybrid(void) +{ + return rc_map_register(&t2hybrid_map); +} + +static void __exit exit_rc_map_t2hybrid(void) +{ + rc_map_unregister(&t2hybrid_map); +} + +module_init(init_rc_map_t2hybrid) +module_exit(exit_rc_map_t2hybrid) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>"); diff --git a/drivers/media/rc/keymaps/rc-avermedia-m135a.c b/drivers/media/rc/keymaps/rc-avermedia-m135a.c index 9882e2cde975..6d5a73b7ccec 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-m135a.c +++ b/drivers/media/rc/keymaps/rc-avermedia-m135a.c @@ -43,7 +43,8 @@ static struct rc_map_table avermedia_m135a[] = { { 0x0213, KEY_RIGHT }, /* -> or L */ { 0x0212, KEY_LEFT }, /* <- or R */ - { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */ + { 0x0215, KEY_MENU }, + { 0x0217, KEY_CAMERA }, /* Capturar Imagem or Snapshot */ { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */ { 0x0303, KEY_CHANNELUP }, diff --git a/drivers/media/rc/keymaps/rc-hisi-poplar.c b/drivers/media/rc/keymaps/rc-hisi-poplar.c new file mode 100644 index 000000000000..78728bc7f63a --- /dev/null +++ b/drivers/media/rc/keymaps/rc-hisi-poplar.c @@ -0,0 +1,69 @@ +/* + * Keytable for remote controller of HiSilicon poplar board. + * + * Copyright (c) 2017 HiSilicon Technologies Co., Ltd. + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/module.h> +#include <media/rc-map.h> + +static struct rc_map_table hisi_poplar_keymap[] = { + { 0x0000b292, KEY_1}, + { 0x0000b293, KEY_2}, + { 0x0000b2cc, KEY_3}, + { 0x0000b28e, KEY_4}, + { 0x0000b28f, KEY_5}, + { 0x0000b2c8, KEY_6}, + { 0x0000b28a, KEY_7}, + { 0x0000b28b, KEY_8}, + { 0x0000b2c4, KEY_9}, + { 0x0000b287, KEY_0}, + { 0x0000b282, KEY_HOMEPAGE}, + { 0x0000b2ca, KEY_UP}, + { 0x0000b299, KEY_LEFT}, + { 0x0000b2c1, KEY_RIGHT}, + { 0x0000b2d2, KEY_DOWN}, + { 0x0000b2c5, KEY_DELETE}, + { 0x0000b29c, KEY_MUTE}, + { 0x0000b281, KEY_VOLUMEDOWN}, + { 0x0000b280, KEY_VOLUMEUP}, + { 0x0000b2dc, KEY_POWER}, + { 0x0000b29a, KEY_MENU}, + { 0x0000b28d, KEY_SETUP}, + { 0x0000b2c5, KEY_BACK}, + { 0x0000b295, KEY_PLAYPAUSE}, + { 0x0000b2ce, KEY_ENTER}, + { 0x0000b285, KEY_CHANNELUP}, + { 0x0000b286, KEY_CHANNELDOWN}, + { 0x0000b2da, KEY_NUMERIC_STAR}, + { 0x0000b2d0, KEY_NUMERIC_POUND}, +}; + +static struct rc_map_list hisi_poplar_map = { + .map = { + .scan = hisi_poplar_keymap, + .size = ARRAY_SIZE(hisi_poplar_keymap), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_HISI_POPLAR, + } +}; + +static int __init init_rc_map_hisi_poplar(void) +{ + return rc_map_register(&hisi_poplar_map); +} + +static void __exit exit_rc_map_hisi_poplar(void) +{ + rc_map_unregister(&hisi_poplar_map); +} + +module_init(init_rc_map_hisi_poplar) +module_exit(exit_rc_map_hisi_poplar) + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/rc/keymaps/rc-hisi-tv-demo.c b/drivers/media/rc/keymaps/rc-hisi-tv-demo.c new file mode 100644 index 000000000000..4816e3a4a18d --- /dev/null +++ b/drivers/media/rc/keymaps/rc-hisi-tv-demo.c @@ -0,0 +1,81 @@ +/* + * Keytable for remote controller of HiSilicon tv demo board. + * + * Copyright (c) 2017 HiSilicon Technologies Co., Ltd. + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/module.h> +#include <media/rc-map.h> + +static struct rc_map_table hisi_tv_demo_keymap[] = { + { 0x00000092, KEY_1}, + { 0x00000093, KEY_2}, + { 0x000000cc, KEY_3}, + { 0x0000009f, KEY_4}, + { 0x0000008e, KEY_5}, + { 0x0000008f, KEY_6}, + { 0x000000c8, KEY_7}, + { 0x00000094, KEY_8}, + { 0x0000008a, KEY_9}, + { 0x0000008b, KEY_0}, + { 0x000000ce, KEY_ENTER}, + { 0x000000ca, KEY_UP}, + { 0x00000099, KEY_LEFT}, + { 0x00000084, KEY_PAGEUP}, + { 0x000000c1, KEY_RIGHT}, + { 0x000000d2, KEY_DOWN}, + { 0x00000089, KEY_PAGEDOWN}, + { 0x000000d1, KEY_MUTE}, + { 0x00000098, KEY_VOLUMEDOWN}, + { 0x00000090, KEY_VOLUMEUP}, + { 0x0000009c, KEY_POWER}, + { 0x000000d6, KEY_STOP}, + { 0x00000097, KEY_MENU}, + { 0x000000cb, KEY_BACK}, + { 0x000000da, KEY_PLAYPAUSE}, + { 0x00000080, KEY_INFO}, + { 0x000000c3, KEY_REWIND}, + { 0x00000087, KEY_HOMEPAGE}, + { 0x000000d0, KEY_FASTFORWARD}, + { 0x000000c4, KEY_SOUND}, + { 0x00000082, BTN_1}, + { 0x000000c7, BTN_2}, + { 0x00000086, KEY_PROGRAM}, + { 0x000000d9, KEY_SUBTITLE}, + { 0x00000085, KEY_ZOOM}, + { 0x0000009b, KEY_RED}, + { 0x0000009a, KEY_GREEN}, + { 0x000000c0, KEY_YELLOW}, + { 0x000000c2, KEY_BLUE}, + { 0x0000009d, KEY_CHANNELDOWN}, + { 0x000000cf, KEY_CHANNELUP}, +}; + +static struct rc_map_list hisi_tv_demo_map = { + .map = { + .scan = hisi_tv_demo_keymap, + .size = ARRAY_SIZE(hisi_tv_demo_keymap), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_HISI_TV_DEMO, + } +}; + +static int __init init_rc_map_hisi_tv_demo(void) +{ + return rc_map_register(&hisi_tv_demo_map); +} + +static void __exit exit_rc_map_hisi_tv_demo(void) +{ + rc_map_unregister(&hisi_tv_demo_map); +} + +module_init(init_rc_map_hisi_tv_demo) +module_exit(exit_rc_map_hisi_tv_demo) + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/rc/keymaps/rc-tango.c b/drivers/media/rc/keymaps/rc-tango.c new file mode 100644 index 000000000000..1c6e8875d46f --- /dev/null +++ b/drivers/media/rc/keymaps/rc-tango.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2017 Sigma Designs + * + * 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. + */ + +#include <linux/module.h> +#include <media/rc-map.h> + +static struct rc_map_table tango_table[] = { + { 0x4cb4a, KEY_POWER }, + { 0x4cb48, KEY_FILE }, + { 0x4cb0f, KEY_SETUP }, + { 0x4cb4d, KEY_SUSPEND }, + { 0x4cb4e, KEY_VOLUMEUP }, + { 0x4cb44, KEY_EJECTCD }, + { 0x4cb13, KEY_TV }, + { 0x4cb51, KEY_MUTE }, + { 0x4cb52, KEY_VOLUMEDOWN }, + + { 0x4cb41, KEY_1 }, + { 0x4cb03, KEY_2 }, + { 0x4cb42, KEY_3 }, + { 0x4cb45, KEY_4 }, + { 0x4cb07, KEY_5 }, + { 0x4cb46, KEY_6 }, + { 0x4cb55, KEY_7 }, + { 0x4cb17, KEY_8 }, + { 0x4cb56, KEY_9 }, + { 0x4cb1b, KEY_0 }, + { 0x4cb59, KEY_DELETE }, + { 0x4cb5a, KEY_CAPSLOCK }, + + { 0x4cb47, KEY_BACK }, + { 0x4cb05, KEY_SWITCHVIDEOMODE }, + { 0x4cb06, KEY_UP }, + { 0x4cb43, KEY_LEFT }, + { 0x4cb01, KEY_RIGHT }, + { 0x4cb0a, KEY_DOWN }, + { 0x4cb02, KEY_ENTER }, + { 0x4cb4b, KEY_INFO }, + { 0x4cb09, KEY_HOME }, + + { 0x4cb53, KEY_MENU }, + { 0x4cb12, KEY_PREVIOUS }, + { 0x4cb50, KEY_PLAY }, + { 0x4cb11, KEY_NEXT }, + { 0x4cb4f, KEY_TITLE }, + { 0x4cb0e, KEY_REWIND }, + { 0x4cb4c, KEY_STOP }, + { 0x4cb0d, KEY_FORWARD }, + { 0x4cb57, KEY_MEDIA_REPEAT }, + { 0x4cb16, KEY_ANGLE }, + { 0x4cb54, KEY_PAUSE }, + { 0x4cb15, KEY_SLOW }, + { 0x4cb5b, KEY_TIME }, + { 0x4cb1a, KEY_AUDIO }, + { 0x4cb58, KEY_SUBTITLE }, + { 0x4cb19, KEY_ZOOM }, + + { 0x4cb5f, KEY_RED }, + { 0x4cb1e, KEY_GREEN }, + { 0x4cb5c, KEY_YELLOW }, + { 0x4cb1d, KEY_BLUE }, +}; + +static struct rc_map_list tango_map = { + .map = { + .scan = tango_table, + .size = ARRAY_SIZE(tango_table), + .rc_proto = RC_PROTO_NECX, + .name = RC_MAP_TANGO, + } +}; + +static int __init init_rc_map_tango(void) +{ + return rc_map_register(&tango_map); +} + +static void __exit exit_rc_map_tango(void) +{ + rc_map_unregister(&tango_map); +} + +module_init(init_rc_map_tango) +module_exit(exit_rc_map_tango) + +MODULE_AUTHOR("Sigma Designs"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/rc/keymaps/rc-twinhan1027.c b/drivers/media/rc/keymaps/rc-twinhan1027.c index 2275b37c61d2..78bb3143a1a8 100644 --- a/drivers/media/rc/keymaps/rc-twinhan1027.c +++ b/drivers/media/rc/keymaps/rc-twinhan1027.c @@ -66,7 +66,7 @@ static struct rc_map_list twinhan_vp1027_map = { .map = { .scan = twinhan_vp1027, .size = ARRAY_SIZE(twinhan_vp1027), - .rc_proto = RC_PROTO_UNKNOWN, /* Legacy IR type */ + .rc_proto = RC_PROTO_NEC, .name = RC_MAP_TWINHAN_VP1027_DVBS, } }; diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 9080e39ea391..e16d1138ca48 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -24,96 +24,91 @@ #include <linux/mutex.h> #include <linux/device.h> #include <linux/cdev.h> +#include <linux/idr.h> #include <media/rc-core.h> #include <media/lirc.h> #include <media/lirc_dev.h> -#define NOPLUG -1 #define LOGHEAD "lirc_dev (%s[%d]): " static dev_t lirc_base_dev; -struct irctl { - struct lirc_driver d; - int attached; - int open; +/* Used to keep track of allocated lirc devices */ +#define LIRC_MAX_DEVICES 256 +static DEFINE_IDA(lirc_ida); - struct mutex irctl_lock; - struct lirc_buffer *buf; - bool buf_internal; - unsigned int chunk_size; - - struct device dev; - struct cdev cdev; -}; +/* Only used for sysfs but defined to void otherwise */ +static struct class *lirc_class; -static DEFINE_MUTEX(lirc_dev_lock); +static void lirc_release_device(struct device *ld) +{ + struct lirc_dev *d = container_of(ld, struct lirc_dev, dev); -static struct irctl *irctls[MAX_IRCTL_DEVICES]; + put_device(d->dev.parent); -/* Only used for sysfs but defined to void otherwise */ -static struct class *lirc_class; + if (d->buf_internal) { + lirc_buffer_free(d->buf); + kfree(d->buf); + d->buf = NULL; + } + kfree(d); + module_put(THIS_MODULE); +} -static void lirc_release(struct device *ld) +static int lirc_allocate_buffer(struct lirc_dev *d) { - struct irctl *ir = container_of(ld, struct irctl, dev); + int err; - put_device(ir->dev.parent); + if (d->buf) { + d->buf_internal = false; + return 0; + } - if (ir->buf_internal) { - lirc_buffer_free(ir->buf); - kfree(ir->buf); + d->buf = kmalloc(sizeof(*d->buf), GFP_KERNEL); + if (!d->buf) + return -ENOMEM; + + err = lirc_buffer_init(d->buf, d->chunk_size, d->buffer_size); + if (err) { + kfree(d->buf); + d->buf = NULL; + return err; } - mutex_lock(&lirc_dev_lock); - irctls[ir->d.minor] = NULL; - mutex_unlock(&lirc_dev_lock); - kfree(ir); + d->buf_internal = true; + return 0; } -static int lirc_allocate_buffer(struct irctl *ir) +struct lirc_dev * +lirc_allocate_device(void) { - int err = 0; - int bytes_in_key; - unsigned int chunk_size; - unsigned int buffer_size; - struct lirc_driver *d = &ir->d; - - bytes_in_key = BITS_TO_LONGS(d->code_length) + - (d->code_length % 8 ? 1 : 0); - buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key; - chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key; - - if (d->rbuf) { - ir->buf = d->rbuf; - ir->buf_internal = false; - } else { - ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - if (!ir->buf) { - err = -ENOMEM; - goto out; - } + struct lirc_dev *d; - err = lirc_buffer_init(ir->buf, chunk_size, buffer_size); - if (err) { - kfree(ir->buf); - ir->buf = NULL; - goto out; - } - - ir->buf_internal = true; - d->rbuf = ir->buf; + d = kzalloc(sizeof(*d), GFP_KERNEL); + if (d) { + mutex_init(&d->mutex); + device_initialize(&d->dev); + d->dev.class = lirc_class; + d->dev.release = lirc_release_device; + __module_get(THIS_MODULE); } - ir->chunk_size = ir->buf->chunk_size; -out: - return err; + return d; } +EXPORT_SYMBOL(lirc_allocate_device); -int lirc_register_driver(struct lirc_driver *d) +void lirc_free_device(struct lirc_dev *d) +{ + if (!d) + return; + + put_device(&d->dev); +} +EXPORT_SYMBOL(lirc_free_device); + +int lirc_register_device(struct lirc_dev *d) { - struct irctl *ir; int minor; int err; @@ -122,8 +117,8 @@ int lirc_register_driver(struct lirc_driver *d) return -EBADRQC; } - if (!d->dev) { - pr_err("dev pointer not filled in!\n"); + if (!d->dev.parent) { + pr_err("dev parent pointer not filled in!\n"); return -EINVAL; } @@ -132,226 +127,146 @@ int lirc_register_driver(struct lirc_driver *d) return -EINVAL; } - if (d->minor >= MAX_IRCTL_DEVICES) { - dev_err(d->dev, "minor must be between 0 and %d!\n", - MAX_IRCTL_DEVICES - 1); - return -EBADRQC; + if (!d->buf && d->chunk_size < 1) { + pr_err("chunk_size must be set!\n"); + return -EINVAL; } - if (d->code_length < 1 || d->code_length > (BUFLEN * 8)) { - dev_err(d->dev, "code length must be less than %d bits\n", - BUFLEN * 8); - return -EBADRQC; + if (!d->buf && d->buffer_size < 1) { + pr_err("buffer_size must be set!\n"); + return -EINVAL; } - if (!d->rbuf && !(d->fops && d->fops->read && - d->fops->poll && d->fops->unlocked_ioctl)) { - dev_err(d->dev, "undefined read, poll, ioctl\n"); + if (d->code_length < 1 || d->code_length > (BUFLEN * 8)) { + dev_err(&d->dev, "code length must be less than %d bits\n", + BUFLEN * 8); return -EBADRQC; } - mutex_lock(&lirc_dev_lock); - - minor = d->minor; - - if (minor < 0) { - /* find first free slot for driver */ - for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) - if (!irctls[minor]) - break; - if (minor == MAX_IRCTL_DEVICES) { - dev_err(d->dev, "no free slots for drivers!\n"); - err = -ENOMEM; - goto out_lock; - } - } else if (irctls[minor]) { - dev_err(d->dev, "minor (%d) just registered!\n", minor); - err = -EBUSY; - goto out_lock; - } - - ir = kzalloc(sizeof(struct irctl), GFP_KERNEL); - if (!ir) { - err = -ENOMEM; - goto out_lock; + if (!d->buf && !(d->fops && d->fops->read && + d->fops->poll && d->fops->unlocked_ioctl)) { + dev_err(&d->dev, "undefined read, poll, ioctl\n"); + return -EBADRQC; } - mutex_init(&ir->irctl_lock); - irctls[minor] = ir; - d->minor = minor; - /* some safety check 8-) */ - d->name[sizeof(d->name)-1] = '\0'; + d->name[sizeof(d->name) - 1] = '\0'; if (d->features == 0) d->features = LIRC_CAN_REC_LIRCCODE; - ir->d = *d; - if (LIRC_CAN_REC(d->features)) { - err = lirc_allocate_buffer(irctls[minor]); - if (err) { - kfree(ir); - goto out_lock; - } - d->rbuf = ir->buf; + err = lirc_allocate_buffer(d); + if (err) + return err; } - device_initialize(&ir->dev); - ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor); - ir->dev.class = lirc_class; - ir->dev.parent = d->dev; - ir->dev.release = lirc_release; - dev_set_name(&ir->dev, "lirc%d", ir->d.minor); + minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL); + if (minor < 0) + return minor; - cdev_init(&ir->cdev, d->fops); - ir->cdev.owner = ir->d.owner; - ir->cdev.kobj.parent = &ir->dev.kobj; - - err = cdev_add(&ir->cdev, ir->dev.devt, 1); - if (err) - goto out_free_dev; - - ir->attached = 1; - - err = device_add(&ir->dev); - if (err) - goto out_cdev; - - mutex_unlock(&lirc_dev_lock); + d->minor = minor; + d->dev.devt = MKDEV(MAJOR(lirc_base_dev), d->minor); + dev_set_name(&d->dev, "lirc%d", d->minor); - get_device(ir->dev.parent); + cdev_init(&d->cdev, d->fops); + d->cdev.owner = d->owner; + d->attached = true; - dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", - ir->d.name, ir->d.minor); + err = cdev_device_add(&d->cdev, &d->dev); + if (err) { + ida_simple_remove(&lirc_ida, minor); + return err; + } - return minor; + get_device(d->dev.parent); -out_cdev: - cdev_del(&ir->cdev); -out_free_dev: - put_device(&ir->dev); -out_lock: - mutex_unlock(&lirc_dev_lock); + dev_info(&d->dev, "lirc_dev: driver %s registered at minor = %d\n", + d->name, d->minor); - return err; + return 0; } -EXPORT_SYMBOL(lirc_register_driver); +EXPORT_SYMBOL(lirc_register_device); -int lirc_unregister_driver(int minor) +void lirc_unregister_device(struct lirc_dev *d) { - struct irctl *ir; + if (!d) + return; - if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { - pr_err("minor (%d) must be between 0 and %d!\n", - minor, MAX_IRCTL_DEVICES - 1); - return -EBADRQC; - } - - ir = irctls[minor]; - if (!ir) { - pr_err("failed to get irctl\n"); - return -ENOENT; - } + dev_dbg(&d->dev, "lirc_dev: driver %s unregistered from minor = %d\n", + d->name, d->minor); - mutex_lock(&lirc_dev_lock); + mutex_lock(&d->mutex); - if (ir->d.minor != minor) { - dev_err(ir->d.dev, "lirc_dev: minor %d device not registered\n", - minor); - mutex_unlock(&lirc_dev_lock); - return -ENOENT; + d->attached = false; + if (d->open) { + dev_dbg(&d->dev, LOGHEAD "releasing opened driver\n", + d->name, d->minor); + wake_up_interruptible(&d->buf->wait_poll); } - dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", - ir->d.name, ir->d.minor); - - ir->attached = 0; - if (ir->open) { - dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n", - ir->d.name, ir->d.minor); - wake_up_interruptible(&ir->buf->wait_poll); - } + mutex_unlock(&d->mutex); - mutex_unlock(&lirc_dev_lock); - - device_del(&ir->dev); - cdev_del(&ir->cdev); - put_device(&ir->dev); - - return 0; + cdev_device_del(&d->cdev, &d->dev); + ida_simple_remove(&lirc_ida, d->minor); + put_device(&d->dev); } -EXPORT_SYMBOL(lirc_unregister_driver); +EXPORT_SYMBOL(lirc_unregister_device); int lirc_dev_fop_open(struct inode *inode, struct file *file) { - struct irctl *ir; - int retval = 0; - - if (iminor(inode) >= MAX_IRCTL_DEVICES) { - pr_err("open result for %d is -ENODEV\n", iminor(inode)); - return -ENODEV; - } - - if (mutex_lock_interruptible(&lirc_dev_lock)) - return -ERESTARTSYS; - - ir = irctls[iminor(inode)]; - mutex_unlock(&lirc_dev_lock); + struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev); + int retval; - if (!ir) { - retval = -ENODEV; - goto error; - } + dev_dbg(&d->dev, LOGHEAD "open called\n", d->name, d->minor); - dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); + retval = mutex_lock_interruptible(&d->mutex); + if (retval) + return retval; - if (ir->d.minor == NOPLUG) { + if (!d->attached) { retval = -ENODEV; - goto error; + goto out; } - if (ir->open) { + if (d->open) { retval = -EBUSY; - goto error; + goto out; } - if (ir->d.rdev) { - retval = rc_open(ir->d.rdev); + if (d->rdev) { + retval = rc_open(d->rdev); if (retval) - goto error; + goto out; } - if (ir->buf) - lirc_buffer_clear(ir->buf); + if (d->buf) + lirc_buffer_clear(d->buf); - ir->open++; + d->open++; -error: + lirc_init_pdata(inode, file); nonseekable_open(inode, file); + mutex_unlock(&d->mutex); + + return 0; +out: + mutex_unlock(&d->mutex); return retval; } EXPORT_SYMBOL(lirc_dev_fop_open); int lirc_dev_fop_close(struct inode *inode, struct file *file) { - struct irctl *ir = irctls[iminor(inode)]; - int ret; - - if (!ir) { - pr_err("called with invalid irctl\n"); - return -EINVAL; - } + struct lirc_dev *d = file->private_data; - ret = mutex_lock_killable(&lirc_dev_lock); - WARN_ON(ret); + mutex_lock(&d->mutex); - rc_close(ir->d.rdev); + rc_close(d->rdev); + d->open--; - ir->open--; - if (!ret) - mutex_unlock(&lirc_dev_lock); + mutex_unlock(&d->mutex); return 0; } @@ -359,29 +274,24 @@ EXPORT_SYMBOL(lirc_dev_fop_close); unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) { - struct irctl *ir = irctls[iminor(file_inode(file))]; + struct lirc_dev *d = file->private_data; unsigned int ret; - if (!ir) { - pr_err("called with invalid irctl\n"); - return POLLERR; - } - - if (!ir->attached) + if (!d->attached) return POLLHUP | POLLERR; - if (ir->buf) { - poll_wait(file, &ir->buf->wait_poll, wait); + if (d->buf) { + poll_wait(file, &d->buf->wait_poll, wait); - if (lirc_buffer_empty(ir->buf)) + if (lirc_buffer_empty(d->buf)) ret = 0; else ret = POLLIN | POLLRDNORM; - } else + } else { ret = POLLERR; + } - dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n", - ir->d.name, ir->d.minor, ret); + dev_dbg(&d->dev, LOGHEAD "poll result = %d\n", d->name, d->minor, ret); return ret; } @@ -389,48 +299,44 @@ EXPORT_SYMBOL(lirc_dev_fop_poll); long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + struct lirc_dev *d = file->private_data; __u32 mode; - int result = 0; - struct irctl *ir = irctls[iminor(file_inode(file))]; + int result; - if (!ir) { - pr_err("no irctl found!\n"); - return -ENODEV; - } + dev_dbg(&d->dev, LOGHEAD "ioctl called (0x%x)\n", + d->name, d->minor, cmd); - dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", - ir->d.name, ir->d.minor, cmd); + result = mutex_lock_interruptible(&d->mutex); + if (result) + return result; - if (ir->d.minor == NOPLUG || !ir->attached) { - dev_err(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n", - ir->d.name, ir->d.minor); - return -ENODEV; + if (!d->attached) { + result = -ENODEV; + goto out; } - mutex_lock(&ir->irctl_lock); - switch (cmd) { case LIRC_GET_FEATURES: - result = put_user(ir->d.features, (__u32 __user *)arg); + result = put_user(d->features, (__u32 __user *)arg); break; case LIRC_GET_REC_MODE: - if (!LIRC_CAN_REC(ir->d.features)) { + if (!LIRC_CAN_REC(d->features)) { result = -ENOTTY; break; } result = put_user(LIRC_REC2MODE - (ir->d.features & LIRC_CAN_REC_MASK), + (d->features & LIRC_CAN_REC_MASK), (__u32 __user *)arg); break; case LIRC_SET_REC_MODE: - if (!LIRC_CAN_REC(ir->d.features)) { + if (!LIRC_CAN_REC(d->features)) { result = -ENOTTY; break; } result = get_user(mode, (__u32 __user *)arg); - if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) + if (!result && !(LIRC_MODE2REC(mode) & d->features)) result = -EINVAL; /* * FIXME: We should actually set the mode somehow but @@ -438,32 +344,14 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) */ break; case LIRC_GET_LENGTH: - result = put_user(ir->d.code_length, (__u32 __user *)arg); - break; - case LIRC_GET_MIN_TIMEOUT: - if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || - ir->d.min_timeout == 0) { - result = -ENOTTY; - break; - } - - result = put_user(ir->d.min_timeout, (__u32 __user *)arg); - break; - case LIRC_GET_MAX_TIMEOUT: - if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || - ir->d.max_timeout == 0) { - result = -ENOTTY; - break; - } - - result = put_user(ir->d.max_timeout, (__u32 __user *)arg); + result = put_user(d->code_length, (__u32 __user *)arg); break; default: result = -ENOTTY; } - mutex_unlock(&ir->irctl_lock); - +out: + mutex_unlock(&d->mutex); return result; } EXPORT_SYMBOL(lirc_dev_fop_ioctl); @@ -473,35 +361,34 @@ ssize_t lirc_dev_fop_read(struct file *file, size_t length, loff_t *ppos) { - struct irctl *ir = irctls[iminor(file_inode(file))]; + struct lirc_dev *d = file->private_data; unsigned char *buf; - int ret = 0, written = 0; + int ret, written = 0; DECLARE_WAITQUEUE(wait, current); - if (!ir) { - pr_err("called with invalid irctl\n"); - return -ENODEV; - } - - if (!LIRC_CAN_REC(ir->d.features)) - return -EINVAL; - - dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); - - buf = kzalloc(ir->chunk_size, GFP_KERNEL); + buf = kzalloc(d->buf->chunk_size, GFP_KERNEL); if (!buf) return -ENOMEM; - if (mutex_lock_interruptible(&ir->irctl_lock)) { - ret = -ERESTARTSYS; - goto out_unlocked; + dev_dbg(&d->dev, LOGHEAD "read called\n", d->name, d->minor); + + ret = mutex_lock_interruptible(&d->mutex); + if (ret) { + kfree(buf); + return ret; } - if (!ir->attached) { + + if (!d->attached) { ret = -ENODEV; goto out_locked; } - if (length % ir->chunk_size) { + if (!LIRC_CAN_REC(d->features)) { + ret = -EINVAL; + goto out_locked; + } + + if (length % d->buf->chunk_size) { ret = -EINVAL; goto out_locked; } @@ -511,14 +398,14 @@ ssize_t lirc_dev_fop_read(struct file *file, * to avoid losing scan code (in case when queue is awaken somewhere * between while condition checking and scheduling) */ - add_wait_queue(&ir->buf->wait_poll, &wait); + add_wait_queue(&d->buf->wait_poll, &wait); /* * while we didn't provide 'length' bytes, device is opened in blocking * mode and 'copy_to_user' is happy, wait for data. */ while (written < length && ret == 0) { - if (lirc_buffer_empty(ir->buf)) { + if (lirc_buffer_empty(d->buf)) { /* According to the read(2) man page, 'written' can be * returned as less than 'length', instead of blocking * again, returning -EWOULDBLOCK, or returning @@ -535,36 +422,36 @@ ssize_t lirc_dev_fop_read(struct file *file, break; } - mutex_unlock(&ir->irctl_lock); + mutex_unlock(&d->mutex); set_current_state(TASK_INTERRUPTIBLE); schedule(); set_current_state(TASK_RUNNING); - if (mutex_lock_interruptible(&ir->irctl_lock)) { - ret = -ERESTARTSYS; - remove_wait_queue(&ir->buf->wait_poll, &wait); + ret = mutex_lock_interruptible(&d->mutex); + if (ret) { + remove_wait_queue(&d->buf->wait_poll, &wait); goto out_unlocked; } - if (!ir->attached) { + if (!d->attached) { ret = -ENODEV; goto out_locked; } } else { - lirc_buffer_read(ir->buf, buf); + lirc_buffer_read(d->buf, buf); ret = copy_to_user((void __user *)buffer+written, buf, - ir->buf->chunk_size); + d->buf->chunk_size); if (!ret) - written += ir->buf->chunk_size; + written += d->buf->chunk_size; else ret = -EFAULT; } } - remove_wait_queue(&ir->buf->wait_poll, &wait); + remove_wait_queue(&d->buf->wait_poll, &wait); out_locked: - mutex_unlock(&ir->irctl_lock); + mutex_unlock(&d->mutex); out_unlocked: kfree(buf); @@ -573,9 +460,19 @@ out_unlocked: } EXPORT_SYMBOL(lirc_dev_fop_read); +void lirc_init_pdata(struct inode *inode, struct file *file) +{ + struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev); + + file->private_data = d; +} +EXPORT_SYMBOL(lirc_init_pdata); + void *lirc_get_pdata(struct file *file) { - return irctls[iminor(file_inode(file))]->d.data; + struct lirc_dev *d = file->private_data; + + return d->data; } EXPORT_SYMBOL(lirc_get_pdata); @@ -590,7 +487,7 @@ static int __init lirc_dev_init(void) return PTR_ERR(lirc_class); } - retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES, + retval = alloc_chrdev_region(&lirc_base_dev, 0, LIRC_MAX_DEVICES, "BaseRemoteCtl"); if (retval) { class_destroy(lirc_class); @@ -607,7 +504,7 @@ static int __init lirc_dev_init(void) static void __exit lirc_dev_exit(void) { class_destroy(lirc_class); - unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES); + unregister_chrdev_region(lirc_base_dev, LIRC_MAX_DEVICES); pr_info("module unloaded\n"); } diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index bf7aaff3aa37..a9187b0b46a1 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -188,6 +188,8 @@ enum mceusb_model_type { TIVO_KIT, MCE_GEN2_NO_TX, HAUPPAUGE_CX_HYBRID_TV, + EVROMEDIA_FULL_HYBRID_FULLHD, + ASTROMETA_T2HYBRID, }; struct mceusb_model { @@ -247,9 +249,19 @@ static const struct mceusb_model mceusb_model[] = { .mce_gen2 = 1, .rc_map = RC_MAP_TIVO, }, + [EVROMEDIA_FULL_HYBRID_FULLHD] = { + .name = "Evromedia USB Full Hybrid Full HD", + .no_tx = 1, + .rc_map = RC_MAP_MSI_DIGIVOX_III, + }, + [ASTROMETA_T2HYBRID] = { + .name = "Astrometa T2Hybrid", + .no_tx = 1, + .rc_map = RC_MAP_ASTROMETA_T2HYBRID, + } }; -static struct usb_device_id mceusb_dev_table[] = { +static const struct usb_device_id mceusb_dev_table[] = { /* Original Microsoft MCE IR Transceiver (often HP-branded) */ { USB_DEVICE(VENDOR_MICROSOFT, 0x006d), .driver_info = MCE_GEN1 }, @@ -398,6 +410,12 @@ static struct usb_device_id mceusb_dev_table[] = { .driver_info = HAUPPAUGE_CX_HYBRID_TV }, /* Adaptec / HP eHome Receiver */ { USB_DEVICE(VENDOR_ADAPTEC, 0x0094) }, + /* Evromedia USB Full Hybrid Full HD */ + { USB_DEVICE(0x1b80, 0xd3b2), + .driver_info = EVROMEDIA_FULL_HYBRID_FULLHD }, + /* Astrometa T2hybrid */ + { USB_DEVICE(0x15f4, 0x0135), + .driver_info = ASTROMETA_T2HYBRID }, /* Terminating entry */ { } diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 7da9c96cb058..ae4dd0c27731 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -106,7 +106,7 @@ struct ir_raw_event_ctrl { } mce_kbd; struct lirc_codec { struct rc_dev *dev; - struct lirc_driver *drv; + struct lirc_dev *ldev; int carrier_low; ktime_t gap_start; diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index 503bc425a187..d78483a504c9 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); /** * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing * @dev: the struct rc_dev device descriptor - * @type: the type of the event that has occurred + * @ev: the event that has occurred * * This routine (which may be called from an interrupt context) works * in similar manner to ir_raw_event_store_edge. @@ -471,9 +471,10 @@ int ir_raw_encode_scancode(enum rc_proto protocol, u32 scancode, } EXPORT_SYMBOL(ir_raw_encode_scancode); -static void edge_handle(unsigned long arg) +static void edge_handle(struct timer_list *t) { - struct rc_dev *dev = (struct rc_dev *)arg; + struct ir_raw_event_ctrl *raw = from_timer(raw, t, edge_handle); + struct rc_dev *dev = raw->dev; ktime_t interval = ktime_sub(ktime_get(), dev->raw->last_event); if (ktime_to_ns(interval) >= dev->timeout) { @@ -513,8 +514,7 @@ int ir_raw_event_prepare(struct rc_dev *dev) dev->raw->dev = dev; dev->change_protocol = change_protocol; - setup_timer(&dev->raw->edge_handle, edge_handle, - (unsigned long)dev); + timer_setup(&dev->raw->edge_handle, edge_handle, 0); INIT_KFIFO(dev->raw->kfifo); return 0; diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 981cccd6b988..c144b77eac98 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -15,6 +15,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <media/rc-core.h> +#include <linux/bsearch.h> #include <linux/spinlock.h> #include <linux/delay.h> #include <linux/input.h> @@ -38,41 +39,41 @@ static const struct { [RC_PROTO_UNKNOWN] = { .name = "unknown", .repeat_period = 250 }, [RC_PROTO_OTHER] = { .name = "other", .repeat_period = 250 }, [RC_PROTO_RC5] = { .name = "rc-5", - .scancode_bits = 0x1f7f, .repeat_period = 164 }, + .scancode_bits = 0x1f7f, .repeat_period = 250 }, [RC_PROTO_RC5X_20] = { .name = "rc-5x-20", - .scancode_bits = 0x1f7f3f, .repeat_period = 164 }, + .scancode_bits = 0x1f7f3f, .repeat_period = 250 }, [RC_PROTO_RC5_SZ] = { .name = "rc-5-sz", - .scancode_bits = 0x2fff, .repeat_period = 164 }, + .scancode_bits = 0x2fff, .repeat_period = 250 }, [RC_PROTO_JVC] = { .name = "jvc", .scancode_bits = 0xffff, .repeat_period = 250 }, [RC_PROTO_SONY12] = { .name = "sony-12", - .scancode_bits = 0x1f007f, .repeat_period = 100 }, + .scancode_bits = 0x1f007f, .repeat_period = 250 }, [RC_PROTO_SONY15] = { .name = "sony-15", - .scancode_bits = 0xff007f, .repeat_period = 100 }, + .scancode_bits = 0xff007f, .repeat_period = 250 }, [RC_PROTO_SONY20] = { .name = "sony-20", - .scancode_bits = 0x1fff7f, .repeat_period = 100 }, + .scancode_bits = 0x1fff7f, .repeat_period = 250 }, [RC_PROTO_NEC] = { .name = "nec", - .scancode_bits = 0xffff, .repeat_period = 160 }, + .scancode_bits = 0xffff, .repeat_period = 250 }, [RC_PROTO_NECX] = { .name = "nec-x", - .scancode_bits = 0xffffff, .repeat_period = 160 }, + .scancode_bits = 0xffffff, .repeat_period = 250 }, [RC_PROTO_NEC32] = { .name = "nec-32", - .scancode_bits = 0xffffffff, .repeat_period = 160 }, + .scancode_bits = 0xffffffff, .repeat_period = 250 }, [RC_PROTO_SANYO] = { .name = "sanyo", .scancode_bits = 0x1fffff, .repeat_period = 250 }, [RC_PROTO_MCIR2_KBD] = { .name = "mcir2-kbd", - .scancode_bits = 0xffff, .repeat_period = 150 }, + .scancode_bits = 0xffff, .repeat_period = 250 }, [RC_PROTO_MCIR2_MSE] = { .name = "mcir2-mse", - .scancode_bits = 0x1fffff, .repeat_period = 150 }, + .scancode_bits = 0x1fffff, .repeat_period = 250 }, [RC_PROTO_RC6_0] = { .name = "rc-6-0", - .scancode_bits = 0xffff, .repeat_period = 164 }, + .scancode_bits = 0xffff, .repeat_period = 250 }, [RC_PROTO_RC6_6A_20] = { .name = "rc-6-6a-20", - .scancode_bits = 0xfffff, .repeat_period = 164 }, + .scancode_bits = 0xfffff, .repeat_period = 250 }, [RC_PROTO_RC6_6A_24] = { .name = "rc-6-6a-24", - .scancode_bits = 0xffffff, .repeat_period = 164 }, + .scancode_bits = 0xffffff, .repeat_period = 250 }, [RC_PROTO_RC6_6A_32] = { .name = "rc-6-6a-32", - .scancode_bits = 0xffffffff, .repeat_period = 164 }, + .scancode_bits = 0xffffffff, .repeat_period = 250 }, [RC_PROTO_RC6_MCE] = { .name = "rc-6-mce", - .scancode_bits = 0xffff7fff, .repeat_period = 164 }, + .scancode_bits = 0xffff7fff, .repeat_period = 250 }, [RC_PROTO_SHARP] = { .name = "sharp", .scancode_bits = 0x1fff, .repeat_period = 250 }, [RC_PROTO_XMP] = { .name = "xmp", .repeat_period = 250 }, @@ -169,10 +170,11 @@ static struct rc_map_list empty_map = { * @name: name to assign to the table * @rc_proto: ir type to assign to the new table * @size: initial size of the table - * @return: zero on success or a negative error code * * This routine will initialize the rc_map and will allocate * memory to hold at least the specified number of elements. + * + * return: zero on success or a negative error code */ static int ir_create_table(struct rc_map *rc_map, const char *name, u64 rc_proto, size_t size) @@ -215,10 +217,11 @@ static void ir_free_table(struct rc_map *rc_map) * ir_resize_table() - resizes a scancode table if necessary * @rc_map: the rc_map to resize * @gfp_flags: gfp flags to use when allocating memory - * @return: zero on success or a negative error code * * This routine will shrink the rc_map if it has lots of * unused entries and grow it if it is full. + * + * return: zero on success or a negative error code */ static int ir_resize_table(struct rc_map *rc_map, gfp_t gfp_flags) { @@ -264,11 +267,13 @@ static int ir_resize_table(struct rc_map *rc_map, gfp_t gfp_flags) * @dev: the struct rc_dev device descriptor * @rc_map: scancode table to be adjusted * @index: index of the mapping that needs to be updated - * @keycode: the desired keycode - * @return: previous keycode assigned to the mapping + * @new_keycode: the desired keycode * * This routine is used to update scancode->keycode mapping at given * position. + * + * return: previous keycode assigned to the mapping + * */ static unsigned int ir_update_mapping(struct rc_dev *dev, struct rc_map *rc_map, @@ -319,12 +324,13 @@ static unsigned int ir_update_mapping(struct rc_dev *dev, * @scancode: the desired scancode * @resize: controls whether we allowed to resize the table to * accommodate not yet present scancodes - * @return: index of the mapping containing scancode in question - * or -1U in case of failure. * * This routine is used to locate given scancode in rc_map. * If scancode is not yet present the routine will allocate a new slot * for it. + * + * return: index of the mapping containing scancode in question + * or -1U in case of failure. */ static unsigned int ir_establish_scancode(struct rc_dev *dev, struct rc_map *rc_map, @@ -374,11 +380,12 @@ static unsigned int ir_establish_scancode(struct rc_dev *dev, /** * ir_setkeycode() - set a keycode in the scancode->keycode table * @idev: the struct input_dev device descriptor - * @scancode: the desired scancode - * @keycode: result - * @return: -EINVAL if the keycode could not be inserted, otherwise zero. + * @ke: Input keymap entry + * @old_keycode: result * * This routine is used to handle evdev EVIOCSKEY ioctl. + * + * return: -EINVAL if the keycode could not be inserted, otherwise zero. */ static int ir_setkeycode(struct input_dev *idev, const struct input_keymap_entry *ke, @@ -421,11 +428,11 @@ out: /** * ir_setkeytable() - sets several entries in the scancode->keycode table * @dev: the struct rc_dev device descriptor - * @to: the struct rc_map to copy entries to * @from: the struct rc_map to copy entries from - * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero. * * This routine is used to handle table initialization. + * + * return: -ENOMEM if all keycodes could not be inserted, otherwise zero. */ static int ir_setkeytable(struct rc_dev *dev, const struct rc_map *from) @@ -439,9 +446,6 @@ static int ir_setkeytable(struct rc_dev *dev, if (rc) return rc; - IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", - rc_map->size, rc_map->alloc); - for (i = 0; i < from->size; i++) { index = ir_establish_scancode(dev, rc_map, from->scan[i].scancode, false); @@ -460,43 +464,49 @@ static int ir_setkeytable(struct rc_dev *dev, return rc; } +static int rc_map_cmp(const void *key, const void *elt) +{ + const unsigned int *scancode = key; + const struct rc_map_table *e = elt; + + if (*scancode < e->scancode) + return -1; + else if (*scancode > e->scancode) + return 1; + return 0; +} + /** * ir_lookup_by_scancode() - locate mapping by scancode * @rc_map: the struct rc_map to search * @scancode: scancode to look for in the table - * @return: index in the table, -1U if not found * * This routine performs binary search in RC keykeymap table for * given scancode. + * + * return: index in the table, -1U if not found */ static unsigned int ir_lookup_by_scancode(const struct rc_map *rc_map, unsigned int scancode) { - int start = 0; - int end = rc_map->len - 1; - int mid; - - while (start <= end) { - mid = (start + end) / 2; - if (rc_map->scan[mid].scancode < scancode) - start = mid + 1; - else if (rc_map->scan[mid].scancode > scancode) - end = mid - 1; - else - return mid; - } + struct rc_map_table *res; - return -1U; + res = bsearch(&scancode, rc_map->scan, rc_map->len, + sizeof(struct rc_map_table), rc_map_cmp); + if (!res) + return -1U; + else + return res - rc_map->scan; } /** * ir_getkeycode() - get a keycode from the scancode->keycode table * @idev: the struct input_dev device descriptor - * @scancode: the desired scancode - * @keycode: used to return the keycode, if found, or KEY_RESERVED - * @return: always returns zero. + * @ke: Input keymap entry * * This routine is used to handle evdev EVIOCGKEY ioctl. + * + * return: always returns zero. */ static int ir_getkeycode(struct input_dev *idev, struct input_keymap_entry *ke) @@ -553,11 +563,12 @@ out: * rc_g_keycode_from_table() - gets the keycode that corresponds to a scancode * @dev: the struct rc_dev descriptor of the device * @scancode: the scancode to look for - * @return: the corresponding keycode, or KEY_RESERVED * * This routine is used by drivers which need to convert a scancode to a * keycode. Normally it should not be used since drivers should have no * interest in keycodes. + * + * return: the corresponding keycode, or KEY_RESERVED */ u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode) { @@ -622,14 +633,15 @@ EXPORT_SYMBOL_GPL(rc_keyup); /** * ir_timer_keyup() - generates a keyup event after a timeout - * @cookie: a pointer to the struct rc_dev for the device + * + * @t: a pointer to the struct timer_list * * This routine will generate a keyup event some time after a keydown event * is generated when no further activity has been detected. */ -static void ir_timer_keyup(unsigned long cookie) +static void ir_timer_keyup(struct timer_list *t) { - struct rc_dev *dev = (struct rc_dev *)cookie; + struct rc_dev *dev = from_timer(dev, t, timer_keyup); unsigned long flags; /* @@ -777,7 +789,8 @@ EXPORT_SYMBOL_GPL(rc_keydown_notimeout); * provides sensible defaults * @dev: the struct rc_dev descriptor of the device * @filter: the scancode and mask - * @return: 0 or -EINVAL if the filter is not valid + * + * return: 0 or -EINVAL if the filter is not valid */ static int rc_validate_filter(struct rc_dev *dev, struct rc_scancode_filter *filter) @@ -1480,6 +1493,8 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name); if (dev->driver_name) ADD_HOTPLUG_VAR("DRV_NAME=%s", dev->driver_name); + if (dev->device_name) + ADD_HOTPLUG_VAR("DEV_NAME=%s", dev->device_name); return 0; } @@ -1487,7 +1502,10 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) /* * Static device attribute struct with the sysfs attributes for IR's */ -static DEVICE_ATTR(protocols, 0644, show_protocols, store_protocols); +static struct device_attribute dev_attr_ro_protocols = +__ATTR(protocols, 0444, show_protocols, NULL); +static struct device_attribute dev_attr_rw_protocols = +__ATTR(protocols, 0644, show_protocols, store_protocols); static DEVICE_ATTR(wakeup_protocols, 0644, show_wakeup_protocols, store_wakeup_protocols); static RC_FILTER_ATTR(filter, S_IRUGO|S_IWUSR, @@ -1499,13 +1517,22 @@ static RC_FILTER_ATTR(wakeup_filter, S_IRUGO|S_IWUSR, static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR, show_filter, store_filter, RC_FILTER_WAKEUP, true); -static struct attribute *rc_dev_protocol_attrs[] = { - &dev_attr_protocols.attr, +static struct attribute *rc_dev_rw_protocol_attrs[] = { + &dev_attr_rw_protocols.attr, NULL, }; -static const struct attribute_group rc_dev_protocol_attr_grp = { - .attrs = rc_dev_protocol_attrs, +static const struct attribute_group rc_dev_rw_protocol_attr_grp = { + .attrs = rc_dev_rw_protocol_attrs, +}; + +static struct attribute *rc_dev_ro_protocol_attrs[] = { + &dev_attr_ro_protocols.attr, + NULL, +}; + +static const struct attribute_group rc_dev_ro_protocol_attr_grp = { + .attrs = rc_dev_ro_protocol_attrs, }; static struct attribute *rc_dev_filter_attrs[] = { @@ -1529,7 +1556,7 @@ static const struct attribute_group rc_dev_wakeup_filter_attr_grp = { .attrs = rc_dev_wakeup_filter_attrs, }; -static struct device_type rc_dev_type = { +static const struct device_type rc_dev_type = { .release = rc_dev_release, .uevent = rc_dev_uevent, }; @@ -1553,8 +1580,7 @@ struct rc_dev *rc_allocate_device(enum rc_driver_type type) dev->input_dev->setkeycode = ir_setkeycode; input_set_drvdata(dev->input_dev, dev); - setup_timer(&dev->timer_keyup, ir_timer_keyup, - (unsigned long)dev); + timer_setup(&dev->timer_keyup, ir_timer_keyup, 0); spin_lock_init(&dev->rc_map.lock); spin_lock_init(&dev->keylock); @@ -1638,6 +1664,9 @@ static int rc_prepare_rx_device(struct rc_dev *dev) rc_proto = BIT_ULL(rc_map->rc_proto); + if (dev->driver_type == RC_DRIVER_SCANCODE && !dev->change_protocol) + dev->enabled_protocols = dev->allowed_protocols; + if (dev->change_protocol) { rc = dev->change_protocol(dev, &rc_proto); if (rc < 0) @@ -1729,8 +1758,10 @@ int rc_register_device(struct rc_dev *dev) dev_set_drvdata(&dev->dev, dev); dev->dev.groups = dev->sysfs_groups; - if (dev->driver_type != RC_DRIVER_IR_RAW_TX) - dev->sysfs_groups[attr++] = &rc_dev_protocol_attr_grp; + if (dev->driver_type == RC_DRIVER_SCANCODE && !dev->change_protocol) + dev->sysfs_groups[attr++] = &rc_dev_ro_protocol_attr_grp; + else if (dev->driver_type != RC_DRIVER_IR_RAW_TX) + dev->sysfs_groups[attr++] = &rc_dev_rw_protocol_attr_grp; if (dev->s_filter) dev->sysfs_groups[attr++] = &rc_dev_filter_attr_grp; if (dev->s_wakeup_filter) diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 6784cb9fc4e7..6bfc24885b5c 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -186,7 +186,7 @@ struct redrat3_error { } __packed; /* table of devices that work with this driver */ -static struct usb_device_id redrat3_dev_table[] = { +static const struct usb_device_id redrat3_dev_table[] = { /* Original version of the RedRat3 */ {USB_DEVICE(USB_RR3USB_VENDOR_ID, USB_RR3USB_PRODUCT_ID)}, /* Second Version/release of the RedRat3 - RetRat3-II */ diff --git a/drivers/media/rc/serial_ir.c b/drivers/media/rc/serial_ir.c index 8b66926bc16a..8bf5637b3a69 100644 --- a/drivers/media/rc/serial_ir.c +++ b/drivers/media/rc/serial_ir.c @@ -470,7 +470,7 @@ static int hardware_init_port(void) return 0; } -static void serial_ir_timeout(unsigned long arg) +static void serial_ir_timeout(struct timer_list *unused) { DEFINE_IR_RAW_EVENT(ev); @@ -540,8 +540,7 @@ static int serial_ir_probe(struct platform_device *dev) serial_ir.rcdev = rcdev; - setup_timer(&serial_ir.timeout_timer, serial_ir_timeout, - (unsigned long)&serial_ir); + timer_setup(&serial_ir.timeout_timer, serial_ir_timeout, 0); result = devm_request_irq(&dev->dev, irq, serial_ir_irq_handler, share_irq ? IRQF_SHARED : 0, diff --git a/drivers/media/rc/sir_ir.c b/drivers/media/rc/sir_ir.c index bc906fb128d5..9ee2c9196b4d 100644 --- a/drivers/media/rc/sir_ir.c +++ b/drivers/media/rc/sir_ir.c @@ -57,7 +57,7 @@ static void add_read_queue(int flag, unsigned long val); static irqreturn_t sir_interrupt(int irq, void *dev_id); static void send_space(unsigned long len); static void send_pulse(unsigned long len); -static void init_hardware(void); +static int init_hardware(void); static void drop_hardware(void); /* Initialisation */ @@ -120,7 +120,7 @@ static void add_read_queue(int flag, unsigned long val) } /* SECTION: Hardware */ -static void sir_timeout(unsigned long data) +static void sir_timeout(struct timer_list *unused) { /* * if last received signal was a pulse, but receiving stopped @@ -263,11 +263,36 @@ static void send_pulse(unsigned long len) } } -static void init_hardware(void) +static int init_hardware(void) { + u8 scratch, scratch2, scratch3; unsigned long flags; spin_lock_irqsave(&hardware_lock, flags); + + /* + * This is a simple port existence test, borrowed from the autoconfig + * function in drivers/tty/serial/8250/8250_port.c + */ + scratch = sinp(UART_IER); + soutp(UART_IER, 0); +#ifdef __i386__ + outb(0xff, 0x080); +#endif + scratch2 = sinp(UART_IER) & 0x0f; + soutp(UART_IER, 0x0f); +#ifdef __i386__ + outb(0x00, 0x080); +#endif + scratch3 = sinp(UART_IER) & 0x0f; + soutp(UART_IER, scratch); + if (scratch2 != 0 || scratch3 != 0x0f) { + /* we fail, there's nothing here */ + spin_unlock_irqrestore(&hardware_lock, flags); + pr_err("port existence test failed, cannot continue\n"); + return -ENODEV; + } + /* reset UART */ outb(0, io + UART_MCR); outb(0, io + UART_IER); @@ -285,6 +310,8 @@ static void init_hardware(void) /* turn on UART */ outb(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2, io + UART_MCR); spin_unlock_irqrestore(&hardware_lock, flags); + + return 0; } static void drop_hardware(void) @@ -321,7 +348,7 @@ static int sir_ir_probe(struct platform_device *dev) rcdev->timeout = IR_DEFAULT_TIMEOUT; rcdev->dev.parent = &sir_ir_dev->dev; - setup_timer(&timerlist, sir_timeout, 0); + timer_setup(&timerlist, sir_timeout, 0); /* get I/O port access and IRQ line */ if (!devm_request_region(&sir_ir_dev->dev, io, 8, KBUILD_MODNAME)) { @@ -334,14 +361,19 @@ static int sir_ir_probe(struct platform_device *dev) pr_err("IRQ %d already in use.\n", irq); return retval; } + + retval = init_hardware(); + if (retval) { + del_timer_sync(&timerlist); + return retval; + } + pr_info("I/O port 0x%.4x, IRQ %d.\n", io, irq); retval = devm_rc_register_device(&sir_ir_dev->dev, rcdev); if (retval < 0) return retval; - init_hardware(); - return 0; } diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c index a8e39c635f34..d2efd7b2c3bc 100644 --- a/drivers/media/rc/st_rc.c +++ b/drivers/media/rc/st_rc.c @@ -49,7 +49,7 @@ struct st_rc_device { #define IRB_RX_NOISE_SUPPR 0x5c /* noise suppression */ #define IRB_RX_POLARITY_INV 0x68 /* polarity inverter */ -/** +/* * IRQ set: Enable full FIFO 1 -> bit 3; * Enable overrun IRQ 1 -> bit 2; * Enable last symbol IRQ 1 -> bit 1: @@ -72,7 +72,7 @@ static void st_rc_send_lirc_timeout(struct rc_dev *rdev) ir_raw_event_store(rdev, &ev); } -/** +/* * RX graphical example to better understand the difference between ST IR block * output and standard definition used by LIRC (and most of the world!) * @@ -317,7 +317,7 @@ static int st_rc_probe(struct platform_device *pdev) device_init_wakeup(dev, true); dev_pm_set_wake_irq(dev, rc_dev->irq); - /** + /* * for LIRC_MODE_MODE2 or LIRC_MODE_PULSE or LIRC_MODE_RAW * lircd expects a long space first before a signal train to sync. */ diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index f03a174ddf9d..c9a70fda88a8 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -43,7 +43,7 @@ #define USB_STREAMZAP_PRODUCT_ID 0x0000 /* table of devices that work with this driver */ -static struct usb_device_id streamzap_table[] = { +static const struct usb_device_id streamzap_table[] = { /* Streamzap Remote Control */ { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) }, /* Terminating entry */ @@ -191,7 +191,7 @@ static void sz_push_half_space(struct streamzap_ir *sz, sz_push_full_space(sz, value & SZ_SPACE_MASK); } -/** +/* * streamzap_callback - usb IRQ handler callback * * This procedure is invoked on reception of data from @@ -321,7 +321,7 @@ out: return NULL; } -/** +/* * streamzap_probe * * Called by usb-core to associated with a candidate device @@ -450,7 +450,7 @@ free_sz: return retval; } -/** +/* * streamzap_disconnect * * Called by the usb core when the device is removed from the system. diff --git a/drivers/media/rc/tango-ir.c b/drivers/media/rc/tango-ir.c new file mode 100644 index 000000000000..9d4c17230c3a --- /dev/null +++ b/drivers/media/rc/tango-ir.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2015 Mans Rullgard <mans@mansr.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 the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/input.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/of.h> +#include <media/rc-core.h> + +#define DRIVER_NAME "tango-ir" + +#define IR_NEC_CTRL 0x00 +#define IR_NEC_DATA 0x04 +#define IR_CTRL 0x08 +#define IR_RC5_CLK_DIV 0x0c +#define IR_RC5_DATA 0x10 +#define IR_INT 0x14 + +#define NEC_TIME_BASE 560 +#define RC5_TIME_BASE 1778 + +#define RC6_CTRL 0x00 +#define RC6_CLKDIV 0x04 +#define RC6_DATA0 0x08 +#define RC6_DATA1 0x0c +#define RC6_DATA2 0x10 +#define RC6_DATA3 0x14 +#define RC6_DATA4 0x18 + +#define RC6_CARRIER 36000 +#define RC6_TIME_BASE 16 + +#define NEC_CAP(n) ((n) << 24) +#define GPIO_SEL(n) ((n) << 16) +#define DISABLE_NEC (BIT(4) | BIT(8)) +#define ENABLE_RC5 (BIT(0) | BIT(9)) +#define ENABLE_RC6 (BIT(0) | BIT(7)) +#define ACK_IR_INT (BIT(0) | BIT(1)) +#define ACK_RC6_INT (BIT(31)) + +#define NEC_ANY (RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX | RC_PROTO_BIT_NEC32) + +struct tango_ir { + void __iomem *rc5_base; + void __iomem *rc6_base; + struct rc_dev *rc; + struct clk *clk; +}; + +static void tango_ir_handle_nec(struct tango_ir *ir) +{ + u32 v, code; + enum rc_proto proto; + + v = readl_relaxed(ir->rc5_base + IR_NEC_DATA); + if (!v) { + rc_repeat(ir->rc); + return; + } + + code = ir_nec_bytes_to_scancode(v, v >> 8, v >> 16, v >> 24, &proto); + rc_keydown(ir->rc, proto, code, 0); +} + +static void tango_ir_handle_rc5(struct tango_ir *ir) +{ + u32 data, field, toggle, addr, cmd, code; + + data = readl_relaxed(ir->rc5_base + IR_RC5_DATA); + if (data & BIT(31)) + return; + + field = data >> 12 & 1; + toggle = data >> 11 & 1; + addr = data >> 6 & 0x1f; + cmd = (data & 0x3f) | (field ^ 1) << 6; + + code = RC_SCANCODE_RC5(addr, cmd); + rc_keydown(ir->rc, RC_PROTO_RC5, code, toggle); +} + +static void tango_ir_handle_rc6(struct tango_ir *ir) +{ + u32 data0, data1, toggle, mode, addr, cmd, code; + + data0 = readl_relaxed(ir->rc6_base + RC6_DATA0); + data1 = readl_relaxed(ir->rc6_base + RC6_DATA1); + + mode = data0 >> 1 & 7; + if (mode != 0) + return; + + toggle = data0 & 1; + addr = data0 >> 16; + cmd = data1; + + code = RC_SCANCODE_RC6_0(addr, cmd); + rc_keydown(ir->rc, RC_PROTO_RC6_0, code, toggle); +} + +static irqreturn_t tango_ir_irq(int irq, void *dev_id) +{ + struct tango_ir *ir = dev_id; + unsigned int rc5_stat; + unsigned int rc6_stat; + + rc5_stat = readl_relaxed(ir->rc5_base + IR_INT); + writel_relaxed(rc5_stat, ir->rc5_base + IR_INT); + + rc6_stat = readl_relaxed(ir->rc6_base + RC6_CTRL); + writel_relaxed(rc6_stat, ir->rc6_base + RC6_CTRL); + + if (!(rc5_stat & 3) && !(rc6_stat & BIT(31))) + return IRQ_NONE; + + if (rc5_stat & BIT(0)) + tango_ir_handle_rc5(ir); + + if (rc5_stat & BIT(1)) + tango_ir_handle_nec(ir); + + if (rc6_stat & BIT(31)) + tango_ir_handle_rc6(ir); + + return IRQ_HANDLED; +} + +static int tango_change_protocol(struct rc_dev *dev, u64 *rc_type) +{ + struct tango_ir *ir = dev->priv; + u32 rc5_ctrl = DISABLE_NEC; + u32 rc6_ctrl = 0; + + if (*rc_type & NEC_ANY) + rc5_ctrl = 0; + + if (*rc_type & RC_PROTO_BIT_RC5) + rc5_ctrl |= ENABLE_RC5; + + if (*rc_type & RC_PROTO_BIT_RC6_0) + rc6_ctrl = ENABLE_RC6; + + writel_relaxed(rc5_ctrl, ir->rc5_base + IR_CTRL); + writel_relaxed(rc6_ctrl, ir->rc6_base + RC6_CTRL); + + return 0; +} + +static int tango_ir_probe(struct platform_device *pdev) +{ + const char *map_name = RC_MAP_TANGO; + struct device *dev = &pdev->dev; + struct rc_dev *rc; + struct tango_ir *ir; + struct resource *rc5_res; + struct resource *rc6_res; + u64 clkrate, clkdiv; + int irq, err; + u32 val; + + rc5_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!rc5_res) + return -EINVAL; + + rc6_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!rc6_res) + return -EINVAL; + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) + return -EINVAL; + + ir = devm_kzalloc(dev, sizeof(*ir), GFP_KERNEL); + if (!ir) + return -ENOMEM; + + ir->rc5_base = devm_ioremap_resource(dev, rc5_res); + if (IS_ERR(ir->rc5_base)) + return PTR_ERR(ir->rc5_base); + + ir->rc6_base = devm_ioremap_resource(dev, rc6_res); + if (IS_ERR(ir->rc6_base)) + return PTR_ERR(ir->rc6_base); + + ir->clk = devm_clk_get(dev, NULL); + if (IS_ERR(ir->clk)) + return PTR_ERR(ir->clk); + + rc = devm_rc_allocate_device(dev, RC_DRIVER_SCANCODE); + if (!rc) + return -ENOMEM; + + of_property_read_string(dev->of_node, "linux,rc-map-name", &map_name); + + rc->device_name = DRIVER_NAME; + rc->driver_name = DRIVER_NAME; + rc->input_phys = DRIVER_NAME "/input0"; + rc->map_name = map_name; + rc->allowed_protocols = NEC_ANY | RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_0; + rc->change_protocol = tango_change_protocol; + rc->priv = ir; + ir->rc = rc; + + err = clk_prepare_enable(ir->clk); + if (err) + return err; + + clkrate = clk_get_rate(ir->clk); + + clkdiv = clkrate * NEC_TIME_BASE; + do_div(clkdiv, 1000000); + + val = NEC_CAP(31) | GPIO_SEL(12) | clkdiv; + writel_relaxed(val, ir->rc5_base + IR_NEC_CTRL); + + clkdiv = clkrate * RC5_TIME_BASE; + do_div(clkdiv, 1000000); + + writel_relaxed(DISABLE_NEC, ir->rc5_base + IR_CTRL); + writel_relaxed(clkdiv, ir->rc5_base + IR_RC5_CLK_DIV); + writel_relaxed(ACK_IR_INT, ir->rc5_base + IR_INT); + + clkdiv = clkrate * RC6_TIME_BASE; + do_div(clkdiv, RC6_CARRIER); + + writel_relaxed(ACK_RC6_INT, ir->rc6_base + RC6_CTRL); + writel_relaxed((clkdiv >> 2) << 18 | clkdiv, ir->rc6_base + RC6_CLKDIV); + + err = devm_request_irq(dev, irq, tango_ir_irq, IRQF_SHARED, + dev_name(dev), ir); + if (err) + goto err_clk; + + err = devm_rc_register_device(dev, rc); + if (err) + goto err_clk; + + platform_set_drvdata(pdev, ir); + return 0; + +err_clk: + clk_disable_unprepare(ir->clk); + return err; +} + +static int tango_ir_remove(struct platform_device *pdev) +{ + struct tango_ir *ir = platform_get_drvdata(pdev); + + clk_disable_unprepare(ir->clk); + return 0; +} + +static const struct of_device_id tango_ir_dt_ids[] = { + { .compatible = "sigma,smp8642-ir" }, + { } +}; +MODULE_DEVICE_TABLE(of, tango_ir_dt_ids); + +static struct platform_driver tango_ir_driver = { + .probe = tango_ir_probe, + .remove = tango_ir_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = tango_ir_dt_ids, + }, +}; +module_platform_driver(tango_ir_driver); + +MODULE_DESCRIPTION("SMP86xx IR decoder driver"); +MODULE_AUTHOR("Mans Rullgard <mans@mansr.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/tuners/mt2063.c b/drivers/media/tuners/mt2063.c index 8b39d8dc97a0..5c87c5c6a455 100644 --- a/drivers/media/tuners/mt2063.c +++ b/drivers/media/tuners/mt2063.c @@ -1397,9 +1397,9 @@ static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref) * risk of overflow. It accurately calculates * f_ref * num / denom to within 1 HZ with fixed math. * - * @num : Fractional portion of the multiplier + * @f_ref: SRO frequency. + * @num: Fractional portion of the multiplier * @denom: denominator portion of the ratio - * @f_Ref: SRO frequency. * * This calculation handles f_ref as two separate 14-bit fields. * Therefore, a maximum value of 2^28-1 may safely be used for f_ref. @@ -1464,8 +1464,6 @@ static u32 MT2063_CalcLO1Mult(u32 *Div, * @f_LO: desired LO frequency. * @f_LO_Step: Minimum step size for the LO (in Hz). * @f_Ref: SRO frequency. - * @f_Avoid: Range of PLL frequencies to avoid near - * integer multiples of f_Ref (in Hz). * * Returns: Recalculated LO frequency. */ diff --git a/drivers/media/usb/as102/as102_fw.c b/drivers/media/usb/as102/as102_fw.c index 5a28ce3a1d49..38dbc128340d 100644 --- a/drivers/media/usb/as102/as102_fw.c +++ b/drivers/media/usb/as102/as102_fw.c @@ -101,18 +101,23 @@ static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap, unsigned char *cmd, const struct firmware *firmware) { - struct as10x_fw_pkt_t fw_pkt; + struct as10x_fw_pkt_t *fw_pkt; int total_read_bytes = 0, errno = 0; unsigned char addr_has_changed = 0; + fw_pkt = kmalloc(sizeof(*fw_pkt), GFP_KERNEL); + if (!fw_pkt) + return -ENOMEM; + + for (total_read_bytes = 0; total_read_bytes < firmware->size; ) { int read_bytes = 0, data_len = 0; /* parse intel hex line */ read_bytes = parse_hex_line( (u8 *) (firmware->data + total_read_bytes), - fw_pkt.raw.address, - fw_pkt.raw.data, + fw_pkt->raw.address, + fw_pkt->raw.data, &data_len, &addr_has_changed); @@ -122,28 +127,28 @@ static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap, /* detect the end of file */ total_read_bytes += read_bytes; if (total_read_bytes == firmware->size) { - fw_pkt.u.request[0] = 0x00; - fw_pkt.u.request[1] = 0x03; + fw_pkt->u.request[0] = 0x00; + fw_pkt->u.request[1] = 0x03; /* send EOF command */ errno = bus_adap->ops->upload_fw_pkt(bus_adap, (uint8_t *) - &fw_pkt, 2, 0); + fw_pkt, 2, 0); if (errno < 0) goto error; } else { if (!addr_has_changed) { /* prepare command to send */ - fw_pkt.u.request[0] = 0x00; - fw_pkt.u.request[1] = 0x01; + fw_pkt->u.request[0] = 0x00; + fw_pkt->u.request[1] = 0x01; - data_len += sizeof(fw_pkt.u.request); - data_len += sizeof(fw_pkt.raw.address); + data_len += sizeof(fw_pkt->u.request); + data_len += sizeof(fw_pkt->raw.address); /* send cmd to device */ errno = bus_adap->ops->upload_fw_pkt(bus_adap, (uint8_t *) - &fw_pkt, + fw_pkt, data_len, 0); if (errno < 0) @@ -152,6 +157,7 @@ static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap, } } error: + kfree(fw_pkt); return (errno == 0) ? total_read_bytes : errno; } diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c index 34dc7e062471..d9093a3c57c5 100644 --- a/drivers/media/usb/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c @@ -105,9 +105,9 @@ static struct tda18271_config hauppauge_woodbury_tunerconfig = { static void au0828_restart_dvb_streaming(struct work_struct *work); -static void au0828_bulk_timeout(unsigned long data) +static void au0828_bulk_timeout(struct timer_list *t) { - struct au0828_dev *dev = (struct au0828_dev *) data; + struct au0828_dev *dev = from_timer(dev, t, bulk_timeout); dprintk(1, "%s called\n", __func__); dev->bulk_timeout_running = 0; @@ -648,9 +648,7 @@ int au0828_dvb_register(struct au0828_dev *dev) return ret; } - dev->bulk_timeout.function = au0828_bulk_timeout; - dev->bulk_timeout.data = (unsigned long) dev; - init_timer(&dev->bulk_timeout); + timer_setup(&dev->bulk_timeout, au0828_bulk_timeout, 0); return 0; } diff --git a/drivers/media/usb/au0828/au0828-i2c.c b/drivers/media/usb/au0828/au0828-i2c.c index ef7d1b830ca3..1b8ec5d9e7ab 100644 --- a/drivers/media/usb/au0828/au0828-i2c.c +++ b/drivers/media/usb/au0828/au0828-i2c.c @@ -342,7 +342,7 @@ static const struct i2c_adapter au0828_i2c_adap_template = { .algo = &au0828_i2c_algo_template, }; -static struct i2c_client au0828_i2c_client_template = { +static const struct i2c_client au0828_i2c_client_template = { .name = "au0828 internal", }; diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c index 7996eb83a54e..af68afe085b5 100644 --- a/drivers/media/usb/au0828/au0828-input.c +++ b/drivers/media/usb/au0828/au0828-input.c @@ -269,7 +269,7 @@ static void au0828_rc_stop(struct rc_dev *rc) static int au0828_probe_i2c_ir(struct au0828_dev *dev) { int i = 0; - const unsigned short addr_list[] = { + static const unsigned short addr_list[] = { 0x47, I2C_CLIENT_END }; diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c index e0930ce59b8d..9dd6bdb7304f 100644 --- a/drivers/media/usb/au0828/au0828-vbi.c +++ b/drivers/media/usb/au0828/au0828-vbi.c @@ -79,7 +79,7 @@ vbi_buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&dev->slock, flags); } -struct vb2_ops au0828_vbi_qops = { +const struct vb2_ops au0828_vbi_qops = { .queue_setup = vbi_queue_setup, .buf_prepare = vbi_buffer_prepare, .buf_queue = vbi_buffer_queue, diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 9342402b92f7..a240153821e0 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -67,10 +67,10 @@ static inline void print_err_status(struct au0828_dev *dev, switch (status) { case -ENOENT: - errmsg = "unlinked synchronuously"; + errmsg = "unlinked synchronously"; break; case -ECONNRESET: - errmsg = "unlinked asynchronuously"; + errmsg = "unlinked asynchronously"; break; case -ENOSR: errmsg = "Buffer error (overrun)"; @@ -954,9 +954,9 @@ int au0828_analog_unregister(struct au0828_dev *dev) /* This function ensures that video frames continue to be delivered even if the ITU-656 input isn't receiving any data (thereby preventing applications such as tvtime from hanging) */ -static void au0828_vid_buffer_timeout(unsigned long data) +static void au0828_vid_buffer_timeout(struct timer_list *t) { - struct au0828_dev *dev = (struct au0828_dev *) data; + struct au0828_dev *dev = from_timer(dev, t, vid_timeout); struct au0828_dmaqueue *dma_q = &dev->vidq; struct au0828_buffer *buf; unsigned char *vid_data; @@ -978,9 +978,9 @@ static void au0828_vid_buffer_timeout(unsigned long data) spin_unlock_irqrestore(&dev->slock, flags); } -static void au0828_vbi_buffer_timeout(unsigned long data) +static void au0828_vbi_buffer_timeout(struct timer_list *t) { - struct au0828_dev *dev = (struct au0828_dev *) data; + struct au0828_dev *dev = from_timer(dev, t, vbi_timeout); struct au0828_dmaqueue *dma_q = &dev->vbiq; struct au0828_buffer *buf; unsigned char *vbi_data; @@ -1953,10 +1953,8 @@ int au0828_analog_register(struct au0828_dev *dev, INIT_LIST_HEAD(&dev->vidq.active); INIT_LIST_HEAD(&dev->vbiq.active); - setup_timer(&dev->vid_timeout, au0828_vid_buffer_timeout, - (unsigned long)dev); - setup_timer(&dev->vbi_timeout, au0828_vbi_buffer_timeout, - (unsigned long)dev); + timer_setup(&dev->vid_timeout, au0828_vid_buffer_timeout, 0); + timer_setup(&dev->vbi_timeout, au0828_vbi_buffer_timeout, 0); dev->width = NTSC_STD_W; dev->height = NTSC_STD_H; diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 05e445fe0b77..f6f37e8ef51d 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -358,7 +358,7 @@ void au0828_dvb_suspend(struct au0828_dev *dev); void au0828_dvb_resume(struct au0828_dev *dev); /* au0828-vbi.c */ -extern struct vb2_ops au0828_vbi_qops; +extern const struct vb2_ops au0828_vbi_qops; #define dprintk(level, fmt, arg...)\ do { if (au0828_debug & level)\ diff --git a/drivers/media/usb/b2c2/Kconfig b/drivers/media/usb/b2c2/Kconfig index 17d35833980c..a620ae42dfc8 100644 --- a/drivers/media/usb/b2c2/Kconfig +++ b/drivers/media/usb/b2c2/Kconfig @@ -10,6 +10,6 @@ config DVB_B2C2_FLEXCOP_USB_DEBUG bool "Enable debug for the B2C2 FlexCop drivers" depends on DVB_B2C2_FLEXCOP_USB select DVB_B2C2_FLEXCOP_DEBUG - help - Say Y if you want to enable the module option to control debug messages - of all B2C2 FlexCop drivers. + help + Say Y if you want to enable the module option to control debug messages + of all B2C2 FlexCop drivers. diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index e0daa9b6c2a0..54d9d0cb326f 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -847,7 +847,7 @@ struct cx231xx_board cx231xx_boards[] = { .demod_addr = 0x64, /* 0xc8 >> 1 */ .demod_i2c_master = I2C_1_MUX_3, .has_dvb = 1, - .ir_i2c_master = I2C_0, + .decoder = CX231XX_AVDECODER, .norm = V4L2_STD_PAL, .output_mode = OUT_MODE_VIP11, .tuner_addr = 0x60, /* 0xc0 >> 1 */ @@ -872,6 +872,7 @@ struct cx231xx_board cx231xx_boards[] = { .name = "Astrometa T2hybrid", .tuner_type = TUNER_ABSENT, .has_dvb = 1, + .decoder = CX231XX_AVDECODER, .output_mode = OUT_MODE_VIP11, .agc_analog_digital_select_gpio = 0x01, .ctl_pin_status_mask = 0xffffffc4, @@ -1684,7 +1685,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, nr = dev->devno; assoc_desc = udev->actconfig->intf_assoc[0]; - if (assoc_desc->bFirstInterface != ifnum) { + if (!assoc_desc || assoc_desc->bFirstInterface != ifnum) { dev_err(d, "Not found matching IAD interface\n"); retval = -ENODEV; goto err_if; diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index c18bb33e060e..54abc1a7c8e1 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c @@ -179,10 +179,10 @@ static inline void print_err_status(struct cx231xx *dev, int packet, int status) switch (status) { case -ENOENT: - errmsg = "unlinked synchronuously"; + errmsg = "unlinked synchronously"; break; case -ECONNRESET: - errmsg = "unlinked asynchronuously"; + errmsg = "unlinked asynchronously"; break; case -ENOSR: errmsg = "Buffer error (overrun)"; diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c index 76e901920f6f..d3bfe8e23b1f 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c @@ -43,10 +43,10 @@ static inline void print_err_status(struct cx231xx *dev, int packet, int status) switch (status) { case -ENOENT: - errmsg = "unlinked synchronuously"; + errmsg = "unlinked synchronously"; break; case -ECONNRESET: - errmsg = "unlinked asynchronuously"; + errmsg = "unlinked asynchronously"; break; case -ENOSR: errmsg = "Buffer error (overrun)"; @@ -285,7 +285,7 @@ static void vbi_buffer_release(struct videobuf_queue *vq, free_buffer(vq, buf); } -struct videobuf_queue_ops cx231xx_vbi_qops = { +const struct videobuf_queue_ops cx231xx_vbi_qops = { .buf_setup = vbi_buffer_setup, .buf_prepare = vbi_buffer_prepare, .buf_queue = vbi_buffer_queue, diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.h b/drivers/media/usb/cx231xx/cx231xx-vbi.h index 16c7d20a22a4..b33d2bdb621c 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.h +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.h @@ -22,7 +22,7 @@ #ifndef _CX231XX_VBI_H #define _CX231XX_VBI_H -extern struct videobuf_queue_ops cx231xx_vbi_qops; +extern const struct videobuf_queue_ops cx231xx_vbi_qops; #define NTSC_VBI_START_LINE 10 /* line 10 - 21 */ #define NTSC_VBI_END_LINE 21 diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 179b8481a870..226059fc672b 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -199,10 +199,10 @@ static inline void print_err_status(struct cx231xx *dev, int packet, int status) switch (status) { case -ENOENT: - errmsg = "unlinked synchronuously"; + errmsg = "unlinked synchronously"; break; case -ECONNRESET: - errmsg = "unlinked asynchronuously"; + errmsg = "unlinked asynchronously"; break; case -ENOSR: errmsg = "Buffer error (overrun)"; diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 096bb75a24e5..2bf3bd81280a 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -628,8 +628,7 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe) } ret = dvb_usbv2_device_power_ctrl(d, 0); - if (ret < 0) - goto err; + err: if (!adap->suspend_resume_active) { adap->active_fe = -1; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c index 0eb33e043079..a221bb8a12b4 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c @@ -516,7 +516,6 @@ static int mxl111sf_i2c_hw_xfer_msg(struct mxl111sf_state *state, data required to program */ block_len = (msg->len / 8); left_over_len = (msg->len % 8); - index = 0; mxl_i2c("block_len %d, left_over_len %d", block_len, left_over_len); diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 95a7b9123f8e..c76e78f9638a 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1598,7 +1598,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) struct rtl28xxu_dev *dev = d->priv; u8 buf[5]; u32 rc_code; - struct rtl28xxu_reg_val rc_nec_tab[] = { + static const struct rtl28xxu_reg_val rc_nec_tab[] = { { 0x3033, 0x80 }, { 0x3020, 0x43 }, { 0x3021, 0x16 }, diff --git a/drivers/media/usb/dvb-usb/a800.c b/drivers/media/usb/dvb-usb/a800.c index 7ba975bea96a..540886b3bb29 100644 --- a/drivers/media/usb/dvb-usb/a800.c +++ b/drivers/media/usb/dvb-usb/a800.c @@ -37,48 +37,9 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr return 0; } -static struct rc_map_table rc_map_a800_table[] = { - { 0x0201, KEY_MODE }, /* SOURCE */ - { 0x0200, KEY_POWER2 }, /* POWER */ - { 0x0205, KEY_1 }, /* 1 */ - { 0x0206, KEY_2 }, /* 2 */ - { 0x0207, KEY_3 }, /* 3 */ - { 0x0209, KEY_4 }, /* 4 */ - { 0x020a, KEY_5 }, /* 5 */ - { 0x020b, KEY_6 }, /* 6 */ - { 0x020d, KEY_7 }, /* 7 */ - { 0x020e, KEY_8 }, /* 8 */ - { 0x020f, KEY_9 }, /* 9 */ - { 0x0212, KEY_LEFT }, /* L / DISPLAY */ - { 0x0211, KEY_0 }, /* 0 */ - { 0x0213, KEY_RIGHT }, /* R / CH RTN */ - { 0x0217, KEY_CAMERA }, /* SNAP SHOT */ - { 0x0210, KEY_LAST }, /* 16-CH PREV */ - { 0x021e, KEY_VOLUMEDOWN }, /* VOL DOWN */ - { 0x020c, KEY_ZOOM }, /* FULL SCREEN */ - { 0x021f, KEY_VOLUMEUP }, /* VOL UP */ - { 0x0214, KEY_MUTE }, /* MUTE */ - { 0x0208, KEY_AUDIO }, /* AUDIO */ - { 0x0219, KEY_RECORD }, /* RECORD */ - { 0x0218, KEY_PLAY }, /* PLAY */ - { 0x021b, KEY_STOP }, /* STOP */ - { 0x021a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */ - { 0x021d, KEY_BACK }, /* << / RED */ - { 0x021c, KEY_FORWARD }, /* >> / YELLOW */ - { 0x0203, KEY_TEXT }, /* TELETEXT */ - { 0x0204, KEY_EPG }, /* EPG */ - { 0x0215, KEY_MENU }, /* MENU */ - - { 0x0303, KEY_CHANNELUP }, /* CH UP */ - { 0x0302, KEY_CHANNELDOWN }, /* CH DOWN */ - { 0x0301, KEY_FIRST }, /* |<< / GREEN */ - { 0x0300, KEY_LAST }, /* >>| / BLUE */ - -}; - -static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +static int a800_rc_query(struct dvb_usb_device *d) { - int ret; + int ret = 0; u8 *key = kmalloc(5, GFP_KERNEL); if (!key) return -ENOMEM; @@ -90,11 +51,12 @@ static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state) goto out; } - /* call the universal NEC remote processor, to find out the key's state and event */ - dvb_usb_nec_rc_key_to_event(d,key,event,state); - if (key[0] != 0) - deb_rc("key: %*ph\n", 5, key); - ret = 0; + /* Note that extended nec and nec32 are dropped */ + if (key[0] == 1) + rc_keydown(d->rc_dev, RC_PROTO_NEC, + RC_SCANCODE_NEC(key[1], key[3]), 0); + else if (key[0] == 2) + rc_repeat(d->rc_dev); out: kfree(key); return ret; @@ -157,11 +119,12 @@ static struct dvb_usb_device_properties a800_properties = { .power_ctrl = a800_power_ctrl, .identify_state = a800_identify_state, - .rc.legacy = { - .rc_interval = DEFAULT_RC_INTERVAL, - .rc_map_table = rc_map_a800_table, - .rc_map_size = ARRAY_SIZE(rc_map_a800_table), - .rc_query = a800_rc_query, + .rc.core = { + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_codes = RC_MAP_AVERMEDIA_M135A, + .module_name = KBUILD_MODNAME, + .rc_query = a800_rc_query, + .allowed_protos = RC_PROTO_BIT_NEC, }, .i2c_algo = &dibusb_i2c_algo, diff --git a/drivers/media/usb/dvb-usb/cinergyT2-fe.c b/drivers/media/usb/dvb-usb/cinergyT2-fe.c index f9772ad0a2a5..5a2f81311fb7 100644 --- a/drivers/media/usb/dvb-usb/cinergyT2-fe.c +++ b/drivers/media/usb/dvb-usb/cinergyT2-fe.c @@ -26,7 +26,7 @@ #include "cinergyT2.h" -/** +/* * convert linux-dvb frontend parameter set into TPS. * See ETSI ETS-300744, section 4.6.2, table 9 for details. * diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 6020170fe99a..366b05529915 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c @@ -291,7 +291,7 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap) stk7700d_dib7000p_mt2266_config) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } } @@ -325,7 +325,7 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap) stk7700d_dib7000p_mt2266_config) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } } @@ -478,7 +478,7 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap) &stk7700ph_dib7700_xc3028_config) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } @@ -1010,7 +1010,7 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) &dib7070p_dib7000p_config) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } @@ -1068,7 +1068,7 @@ static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap) &dib7770p_dib7000p_config) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } @@ -1677,10 +1677,10 @@ static int dib8096_set_param_override(struct dvb_frontend *fe) return -EINVAL; } - /** Update PLL if needed ratio **/ + /* Update PLL if needed ratio */ state->dib8000_ops.update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, 0); - /** Get optimize PLL ratio to remove spurious **/ + /* Get optimize PLL ratio to remove spurious */ pll_ratio = dib8090_compute_pll_parameters(fe); if (pll_ratio == 17) timf = 21387946; @@ -1691,7 +1691,7 @@ static int dib8096_set_param_override(struct dvb_frontend *fe) else timf = 18179756; - /** Update ratio **/ + /* Update ratio */ state->dib8000_ops.update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, pll_ratio); state->dib8000_ops.ctrl_timf(fe, DEMOD_TIMF_SET, timf); @@ -3056,7 +3056,7 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap) if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config); @@ -3109,7 +3109,7 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap) /* initialize IC 0 */ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } @@ -3139,7 +3139,7 @@ static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap) i2c = state->dib7000p_ops.get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1); if (state->dib7000p_ops.i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } @@ -3214,7 +3214,7 @@ static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap) 1, 0x10, &tfe7790p_dib7000p_config) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, @@ -3309,7 +3309,7 @@ static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap) stk7070pd_dib7000p_config) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } @@ -3357,7 +3357,7 @@ static int novatd_sleep_override(struct dvb_frontend* fe) return state->sleep(fe); } -/** +/* * novatd_frontend_attach - Nova-TD specific attach * * Nova-TD has GPIO0, 1 and 2 for LEDs. So do not fiddle with them except for @@ -3384,7 +3384,7 @@ static int novatd_frontend_attach(struct dvb_usb_adapter *adap) stk7070pd_dib7000p_config) != 0) { err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } } @@ -3620,7 +3620,7 @@ static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap) if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap) == 0) { /* Demodulator not found for some reason? */ - dvb_detach(&state->dib7000p_ops); + dvb_detach(state->dib7000p_ops.set_wbd_ref); return -ENODEV; } diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c index 8207e6900656..bcacb0f22028 100644 --- a/drivers/media/usb/dvb-usb/dibusb-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-common.c @@ -223,8 +223,20 @@ EXPORT_SYMBOL(dibusb_i2c_algo); int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) { - u8 wbuf[1] = { offs }; - return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1); + u8 *buf; + int rc; + + buf = kmalloc(2, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf[0] = offs; + + rc = dibusb_i2c_msg(d, 0x50, &buf[0], 1, &buf[1], 1); + *val = buf[1]; + kfree(buf); + + return rc; } EXPORT_SYMBOL(dibusb_read_eeprom_byte); diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c index 701c10835482..65e2c9e2cdc9 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c @@ -280,10 +280,11 @@ static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d) dev->change_protocol = d->props.rc.core.change_protocol; dev->allowed_protocols = d->props.rc.core.allowed_protos; usb_to_input_id(d->udev, &dev->input_id); - dev->device_name = "IR-receiver inside an USB DVB receiver"; + dev->device_name = d->desc->name; dev->input_phys = d->rc_phys; dev->dev.parent = &d->udev->dev; dev->priv = d; + dev->scancode_mask = d->props.rc.core.scancode_mask; err = rc_register_device(dev); if (err < 0) { diff --git a/drivers/media/usb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h index 6c7c4637530f..e71fc86b4fb2 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb.h +++ b/drivers/media/usb/dvb-usb/dvb-usb.h @@ -208,6 +208,7 @@ struct dvb_rc { int (*rc_query) (struct dvb_usb_device *d); int rc_interval; bool bulk_mode; /* uses bulk mode */ + u32 scancode_mask; }; /** diff --git a/drivers/media/usb/dvb-usb/friio-fe.c b/drivers/media/usb/dvb-usb/friio-fe.c index 0251a4e91d47..b6046e0e07f6 100644 --- a/drivers/media/usb/dvb-usb/friio-fe.c +++ b/drivers/media/usb/dvb-usb/friio-fe.c @@ -261,28 +261,6 @@ static int jdvbt90502_read_signal_strength(struct dvb_frontend *fe, return 0; } - -/* filter out un-supported properties to notify users */ -static int jdvbt90502_set_property(struct dvb_frontend *fe, - struct dtv_property *tvp) -{ - int r = 0; - - switch (tvp->cmd) { - case DTV_DELIVERY_SYSTEM: - if (tvp->u.data != SYS_ISDBT) - r = -EINVAL; - break; - case DTV_CLEAR: - case DTV_TUNE: - case DTV_FREQUENCY: - break; - default: - r = -EINVAL; - } - return r; -} - static int jdvbt90502_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *p = &fe->dtv_property_cache; @@ -319,7 +297,7 @@ static int jdvbt90502_set_frontend(struct dvb_frontend *fe) } -/** +/* * (reg, val) commad list to initialize this module. * captured on a Windows box. */ @@ -457,8 +435,6 @@ static const struct dvb_frontend_ops jdvbt90502_ops = { .init = jdvbt90502_init, .write = _jdvbt90502_write, - .set_property = jdvbt90502_set_property, - .set_frontend = jdvbt90502_set_frontend, .read_status = jdvbt90502_read_status, diff --git a/drivers/media/usb/dvb-usb/friio.c b/drivers/media/usb/dvb-usb/friio.c index 62abe6c43a32..16875945e662 100644 --- a/drivers/media/usb/dvb-usb/friio.c +++ b/drivers/media/usb/dvb-usb/friio.c @@ -21,7 +21,7 @@ MODULE_PARM_DESC(debug, DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -/** +/* * Indirect I2C access to the PLL via FE. * whole I2C protocol data to the PLL is sent via the FE's I2C register. * This is done by a control msg to the FE with the I2C data accompanied, and diff --git a/drivers/media/usb/dvb-usb/vp7045.c b/drivers/media/usb/dvb-usb/vp7045.c index 13340af0d39c..2527b88beb87 100644 --- a/drivers/media/usb/dvb-usb/vp7045.c +++ b/drivers/media/usb/dvb-usb/vp7045.c @@ -97,82 +97,22 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff) return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150); } -/* remote control stuff */ - -/* The keymapping struct. Somehow this should be loaded to the driver, but - * currently it is hardcoded. */ -static struct rc_map_table rc_map_vp7045_table[] = { - { 0x0016, KEY_POWER }, - { 0x0010, KEY_MUTE }, - { 0x0003, KEY_1 }, - { 0x0001, KEY_2 }, - { 0x0006, KEY_3 }, - { 0x0009, KEY_4 }, - { 0x001d, KEY_5 }, - { 0x001f, KEY_6 }, - { 0x000d, KEY_7 }, - { 0x0019, KEY_8 }, - { 0x001b, KEY_9 }, - { 0x0015, KEY_0 }, - { 0x0005, KEY_CHANNELUP }, - { 0x0002, KEY_CHANNELDOWN }, - { 0x001e, KEY_VOLUMEUP }, - { 0x000a, KEY_VOLUMEDOWN }, - { 0x0011, KEY_RECORD }, - { 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */ - { 0x0014, KEY_PLAY }, - { 0x001a, KEY_STOP }, - { 0x0040, KEY_REWIND }, - { 0x0012, KEY_FASTFORWARD }, - { 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */ - { 0x004c, KEY_PAUSE }, - { 0x004d, KEY_SCREEN }, /* Full screen mode. */ - { 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ - { 0x000c, KEY_CANCEL }, /* Cancel */ - { 0x001c, KEY_EPG }, /* EPG */ - { 0x0000, KEY_TAB }, /* Tab */ - { 0x0048, KEY_INFO }, /* Preview */ - { 0x0004, KEY_LIST }, /* RecordList */ - { 0x000f, KEY_TEXT }, /* Teletext */ - { 0x0041, KEY_PREVIOUSSONG }, - { 0x0042, KEY_NEXTSONG }, - { 0x004b, KEY_UP }, - { 0x0051, KEY_DOWN }, - { 0x004e, KEY_LEFT }, - { 0x0052, KEY_RIGHT }, - { 0x004f, KEY_ENTER }, - { 0x0013, KEY_CANCEL }, - { 0x004a, KEY_CLEAR }, - { 0x0054, KEY_PRINT }, /* Capture */ - { 0x0043, KEY_SUBTITLE }, /* Subtitle/CC */ - { 0x0008, KEY_VIDEO }, /* A/V */ - { 0x0007, KEY_SLEEP }, /* Hibernate */ - { 0x0045, KEY_ZOOM }, /* Zoom+ */ - { 0x0018, KEY_RED}, - { 0x0053, KEY_GREEN}, - { 0x005e, KEY_YELLOW}, - { 0x005f, KEY_BLUE} -}; - -static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +static int vp7045_rc_query(struct dvb_usb_device *d) { u8 key; - int i; vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20); deb_rc("remote query key: %x %d\n",key,key); - if (key == 0x44) { - *state = REMOTE_NO_KEY_PRESSED; - return 0; + if (key != 0x44) { + /* + * The 8 bit address isn't available, but since the remote uses + * address 0 we'll use that. nec repeats are ignored too, even + * though the remote sends them. + */ + rc_keydown(d->rc_dev, RC_PROTO_NEC, RC_SCANCODE_NEC(0, key), 0); } - for (i = 0; i < ARRAY_SIZE(rc_map_vp7045_table); i++) - if (rc5_data(&rc_map_vp7045_table[i]) == key) { - *state = REMOTE_KEY_PRESSED; - *event = rc_map_vp7045_table[i].keycode; - break; - } return 0; } @@ -265,11 +205,13 @@ static struct dvb_usb_device_properties vp7045_properties = { .power_ctrl = vp7045_power_ctrl, .read_mac_address = vp7045_read_mac_addr, - .rc.legacy = { - .rc_interval = 400, - .rc_map_table = rc_map_vp7045_table, - .rc_map_size = ARRAY_SIZE(rc_map_vp7045_table), - .rc_query = vp7045_rc_query, + .rc.core = { + .rc_interval = 400, + .rc_codes = RC_MAP_TWINHAN_VP1027_DVBS, + .module_name = KBUILD_MODNAME, + .rc_query = vp7045_rc_query, + .allowed_protos = RC_PROTO_BIT_NEC, + .scancode_mask = 0xff, }, .num_device_descs = 2, diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 4a7db623fe29..9950a740e04e 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -112,10 +112,10 @@ static inline void print_err_status(struct em28xx *dev, switch (status) { case -ENOENT: - errmsg = "unlinked synchronuously"; + errmsg = "unlinked synchronously"; break; case -ECONNRESET: - errmsg = "unlinked asynchronuously"; + errmsg = "unlinked asynchronously"; break; case -ENOSR: errmsg = "Buffer error (overrun)"; diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c index 66c5012a628a..9bf49d666e5a 100644 --- a/drivers/media/usb/em28xx/em28xx-i2c.c +++ b/drivers/media/usb/em28xx/em28xx-i2c.c @@ -882,7 +882,7 @@ static const struct i2c_adapter em28xx_adap_template = { .algo = &em28xx_algo, }; -static struct i2c_client em28xx_client_template = { +static const struct i2c_client em28xx_client_template = { .name = "em28xx internal", }; diff --git a/drivers/media/usb/em28xx/em28xx-v4l.h b/drivers/media/usb/em28xx/em28xx-v4l.h index 8dfcb56bf4b3..9c411aac3878 100644 --- a/drivers/media/usb/em28xx/em28xx-v4l.h +++ b/drivers/media/usb/em28xx/em28xx-v4l.h @@ -16,4 +16,4 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count); void em28xx_stop_vbi_streaming(struct vb2_queue *vq); -extern struct vb2_ops em28xx_vbi_qops; +extern const struct vb2_ops em28xx_vbi_qops; diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c index 0bac552bbe87..f5123651ef30 100644 --- a/drivers/media/usb/em28xx/em28xx-vbi.c +++ b/drivers/media/usb/em28xx/em28xx-vbi.c @@ -93,7 +93,7 @@ vbi_buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&dev->slock, flags); } -struct vb2_ops em28xx_vbi_qops = { +const struct vb2_ops em28xx_vbi_qops = { .queue_setup = vbi_queue_setup, .buf_prepare = vbi_buffer_prepare, .buf_queue = vbi_buffer_queue, diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 8d253a5df0a9..a2ba2d905952 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -557,10 +557,10 @@ static inline void print_err_status(struct em28xx *dev, switch (status) { case -ENOENT: - errmsg = "unlinked synchronuously"; + errmsg = "unlinked synchronously"; break; case -ECONNRESET: - errmsg = "unlinked asynchronuously"; + errmsg = "unlinked asynchronously"; break; case -ENOSR: errmsg = "Buffer error (overrun)"; diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig index 3fd94fe7e1eb..d214a21acff7 100644 --- a/drivers/media/usb/gspca/Kconfig +++ b/drivers/media/usb/gspca/Kconfig @@ -204,11 +204,11 @@ config USB_GSPCA_SE401 tristate "SE401 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the - Endpoints (formerly known as AOX) se401 chip. + Say Y here if you want support for cameras based on the + Endpoints (formerly known as AOX) se401 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_se401. + To compile this driver as a module, choose M here: the + module will be called gspca_se401. config USB_GSPCA_SN9C2028 tristate "SONIX Dual-Mode USB Camera Driver" @@ -224,11 +224,11 @@ config USB_GSPCA_SN9C20X tristate "SN9C20X USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the - sn9c20x chips (SN9C201 and SN9C202). + Say Y here if you want support for cameras based on the + sn9c20x chips (SN9C201 and SN9C202). - To compile this driver as a module, choose M here: the - module will be called gspca_sn9c20x. + To compile this driver as a module, choose M here: the + module will be called gspca_sn9c20x. config USB_GSPCA_SONIXB tristate "SONIX Bayer USB Camera Driver" diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 0f141762abf1..961343873fd0 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1075,7 +1075,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, /* give an index to each format */ index = 0; - j = 0; for (i = gspca_dev->cam.nmodes; --i >= 0; ) { fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixelformat; j = 0; diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c index cdb79c5f0c38..1b30434b72ef 100644 --- a/drivers/media/usb/gspca/ov519.c +++ b/drivers/media/usb/gspca/ov519.c @@ -1,4 +1,4 @@ -/** +/* * OV519 driver * * Copyright (C) 2008-2011 Jean-François Moine <moinejf@free.fr> @@ -2865,7 +2865,7 @@ static void sd_reset_snapshot(struct gspca_dev *gspca_dev) static void ov51x_upload_quan_tables(struct sd *sd) { - const unsigned char yQuanTable511[] = { + static const unsigned char yQuanTable511[] = { 0, 1, 1, 2, 2, 3, 3, 4, 1, 1, 1, 2, 2, 3, 4, 4, 1, 1, 2, 2, 3, 4, 4, 4, @@ -2876,7 +2876,7 @@ static void ov51x_upload_quan_tables(struct sd *sd) 4, 4, 4, 4, 5, 5, 5, 5 }; - const unsigned char uvQuanTable511[] = { + static const unsigned char uvQuanTable511[] = { 0, 2, 2, 3, 4, 4, 4, 4, 2, 2, 2, 4, 4, 4, 4, 4, 2, 2, 3, 4, 4, 4, 4, 4, @@ -2888,13 +2888,13 @@ static void ov51x_upload_quan_tables(struct sd *sd) }; /* OV518 quantization tables are 8x4 (instead of 8x8) */ - const unsigned char yQuanTable518[] = { + static const unsigned char yQuanTable518[] = { 5, 4, 5, 6, 6, 7, 7, 7, 5, 5, 5, 5, 6, 7, 7, 7, 6, 6, 6, 6, 7, 7, 7, 8, 7, 7, 6, 7, 7, 7, 8, 8 }; - const unsigned char uvQuanTable518[] = { + static const unsigned char uvQuanTable518[] = { 6, 6, 6, 7, 7, 7, 7, 7, 6, 6, 6, 7, 7, 7, 7, 7, 6, 6, 6, 7, 7, 7, 7, 8, @@ -2943,7 +2943,7 @@ static void ov511_configure(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; /* For 511 and 511+ */ - const struct ov_regvals init_511[] = { + static const struct ov_regvals init_511[] = { { R51x_SYS_RESET, 0x7f }, { R51x_SYS_INIT, 0x01 }, { R51x_SYS_RESET, 0x7f }, @@ -2953,7 +2953,7 @@ static void ov511_configure(struct gspca_dev *gspca_dev) { R51x_SYS_RESET, 0x3d }, }; - const struct ov_regvals norm_511[] = { + static const struct ov_regvals norm_511[] = { { R511_DRAM_FLOW_CTL, 0x01 }, { R51x_SYS_SNAP, 0x00 }, { R51x_SYS_SNAP, 0x02 }, @@ -2963,7 +2963,7 @@ static void ov511_configure(struct gspca_dev *gspca_dev) { R511_COMP_LUT_EN, 0x03 }, }; - const struct ov_regvals norm_511_p[] = { + static const struct ov_regvals norm_511_p[] = { { R511_DRAM_FLOW_CTL, 0xff }, { R51x_SYS_SNAP, 0x00 }, { R51x_SYS_SNAP, 0x02 }, @@ -2973,7 +2973,7 @@ static void ov511_configure(struct gspca_dev *gspca_dev) { R511_COMP_LUT_EN, 0x03 }, }; - const struct ov_regvals compress_511[] = { + static const struct ov_regvals compress_511[] = { { 0x70, 0x1f }, { 0x71, 0x05 }, { 0x72, 0x06 }, @@ -3009,7 +3009,7 @@ static void ov518_configure(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; /* For 518 and 518+ */ - const struct ov_regvals init_518[] = { + static const struct ov_regvals init_518[] = { { R51x_SYS_RESET, 0x40 }, { R51x_SYS_INIT, 0xe1 }, { R51x_SYS_RESET, 0x3e }, @@ -3020,7 +3020,7 @@ static void ov518_configure(struct gspca_dev *gspca_dev) { 0x5d, 0x03 }, }; - const struct ov_regvals norm_518[] = { + static const struct ov_regvals norm_518[] = { { R51x_SYS_SNAP, 0x02 }, /* Reset */ { R51x_SYS_SNAP, 0x01 }, /* Enable */ { 0x31, 0x0f }, @@ -3033,7 +3033,7 @@ static void ov518_configure(struct gspca_dev *gspca_dev) { 0x2f, 0x80 }, }; - const struct ov_regvals norm_518_p[] = { + static const struct ov_regvals norm_518_p[] = { { R51x_SYS_SNAP, 0x02 }, /* Reset */ { R51x_SYS_SNAP, 0x01 }, /* Enable */ { 0x31, 0x0f }, diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index a097d3dbc141..65ef755adfdc 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -386,7 +386,7 @@ static void msi2500_isoc_handler(struct urb *urb) if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) { - dev_dbg(dev->dev, "URB (%p) unlinked %ssynchronuously\n", + dev_dbg(dev->dev, "URB (%p) unlinked %ssynchronously\n", urb, urb->status == -ENOENT ? "" : "a"); return; } diff --git a/drivers/media/usb/pvrusb2/Kconfig b/drivers/media/usb/pvrusb2/Kconfig index 60a2604e4cb3..1ad913fc30bf 100644 --- a/drivers/media/usb/pvrusb2/Kconfig +++ b/drivers/media/usb/pvrusb2/Kconfig @@ -44,7 +44,6 @@ config VIDEO_PVRUSB2_DVB select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT ---help--- - This option enables a DVB interface for the pvrusb2 driver. If your device does not support digital television, this feature will have no affect on the driver's operation. diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index ad5b25b89699..8289ee482f49 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -330,10 +330,10 @@ static void pvr2_hdw_state_log_state(struct pvr2_hdw *); static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl); static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw); static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); -static void pvr2_hdw_quiescent_timeout(unsigned long); -static void pvr2_hdw_decoder_stabilization_timeout(unsigned long); -static void pvr2_hdw_encoder_wait_timeout(unsigned long); -static void pvr2_hdw_encoder_run_timeout(unsigned long); +static void pvr2_hdw_quiescent_timeout(struct timer_list *); +static void pvr2_hdw_decoder_stabilization_timeout(struct timer_list *); +static void pvr2_hdw_encoder_wait_timeout(struct timer_list *); +static void pvr2_hdw_encoder_run_timeout(struct timer_list *); static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32); static int pvr2_send_request_ex(struct pvr2_hdw *hdw, unsigned int timeout,int probe_fl, @@ -2373,18 +2373,15 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, } if (!hdw) goto fail; - setup_timer(&hdw->quiescent_timer, pvr2_hdw_quiescent_timeout, - (unsigned long)hdw); + timer_setup(&hdw->quiescent_timer, pvr2_hdw_quiescent_timeout, 0); - setup_timer(&hdw->decoder_stabilization_timer, - pvr2_hdw_decoder_stabilization_timeout, - (unsigned long)hdw); + timer_setup(&hdw->decoder_stabilization_timer, + pvr2_hdw_decoder_stabilization_timeout, 0); - setup_timer(&hdw->encoder_wait_timer, pvr2_hdw_encoder_wait_timeout, - (unsigned long)hdw); + timer_setup(&hdw->encoder_wait_timer, pvr2_hdw_encoder_wait_timeout, + 0); - setup_timer(&hdw->encoder_run_timer, pvr2_hdw_encoder_run_timeout, - (unsigned long)hdw); + timer_setup(&hdw->encoder_run_timer, pvr2_hdw_encoder_run_timeout, 0); hdw->master_state = PVR2_STATE_DEAD; @@ -3539,10 +3536,16 @@ static void pvr2_ctl_read_complete(struct urb *urb) complete(&hdw->ctl_done); } +struct hdw_timer { + struct timer_list timer; + struct pvr2_hdw *hdw; +}; -static void pvr2_ctl_timeout(unsigned long data) +static void pvr2_ctl_timeout(struct timer_list *t) { - struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; + struct hdw_timer *timer = from_timer(timer, t, timer); + struct pvr2_hdw *hdw = timer->hdw; + if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) { hdw->ctl_timeout_flag = !0; if (hdw->ctl_write_pend_flag) @@ -3564,7 +3567,10 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, { unsigned int idx; int status = 0; - struct timer_list timer; + struct hdw_timer timer = { + .hdw = hdw, + }; + if (!hdw->ctl_lock_held) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Attempted to execute control transfer without lock!!"); @@ -3621,8 +3627,8 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, hdw->ctl_timeout_flag = 0; hdw->ctl_write_pend_flag = 0; hdw->ctl_read_pend_flag = 0; - setup_timer(&timer, pvr2_ctl_timeout, (unsigned long)hdw); - timer.expires = jiffies + timeout; + timer_setup_on_stack(&timer.timer, pvr2_ctl_timeout, 0); + timer.timer.expires = jiffies + timeout; if (write_len && write_data) { hdw->cmd_debug_state = 2; @@ -3677,7 +3683,7 @@ status); } /* Start timer */ - add_timer(&timer); + add_timer(&timer.timer); /* Now wait for all I/O to complete */ hdw->cmd_debug_state = 4; @@ -3687,7 +3693,7 @@ status); hdw->cmd_debug_state = 5; /* Stop timer */ - del_timer_sync(&timer); + del_timer_sync(&timer.timer); hdw->cmd_debug_state = 6; status = 0; @@ -3769,6 +3775,8 @@ status); if ((status < 0) && (!probe_fl)) { pvr2_hdw_render_useless(hdw); } + destroy_timer_on_stack(&timer.timer); + return status; } @@ -4366,9 +4374,9 @@ static int state_eval_encoder_run(struct pvr2_hdw *hdw) /* Timeout function for quiescent timer. */ -static void pvr2_hdw_quiescent_timeout(unsigned long data) +static void pvr2_hdw_quiescent_timeout(struct timer_list *t) { - struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; + struct pvr2_hdw *hdw = from_timer(hdw, t, quiescent_timer); hdw->state_decoder_quiescent = !0; trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent); hdw->state_stale = !0; @@ -4377,9 +4385,9 @@ static void pvr2_hdw_quiescent_timeout(unsigned long data) /* Timeout function for decoder stabilization timer. */ -static void pvr2_hdw_decoder_stabilization_timeout(unsigned long data) +static void pvr2_hdw_decoder_stabilization_timeout(struct timer_list *t) { - struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; + struct pvr2_hdw *hdw = from_timer(hdw, t, decoder_stabilization_timer); hdw->state_decoder_ready = !0; trace_stbit("state_decoder_ready", hdw->state_decoder_ready); hdw->state_stale = !0; @@ -4388,9 +4396,9 @@ static void pvr2_hdw_decoder_stabilization_timeout(unsigned long data) /* Timeout function for encoder wait timer. */ -static void pvr2_hdw_encoder_wait_timeout(unsigned long data) +static void pvr2_hdw_encoder_wait_timeout(struct timer_list *t) { - struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; + struct pvr2_hdw *hdw = from_timer(hdw, t, encoder_wait_timer); hdw->state_encoder_waitok = !0; trace_stbit("state_encoder_waitok",hdw->state_encoder_waitok); hdw->state_stale = !0; @@ -4399,9 +4407,9 @@ static void pvr2_hdw_encoder_wait_timeout(unsigned long data) /* Timeout function for encoder run timer. */ -static void pvr2_hdw_encoder_run_timeout(unsigned long data) +static void pvr2_hdw_encoder_run_timeout(struct timer_list *t) { - struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; + struct pvr2_hdw *hdw = from_timer(hdw, t, encoder_run_timer); if (!hdw->state_encoder_runok) { hdw->state_encoder_runok = !0; trace_stbit("state_encoder_runok",hdw->state_encoder_runok); diff --git a/drivers/media/usb/pwc/pwc-dec23.c b/drivers/media/usb/pwc/pwc-dec23.c index 3792fedff951..1283b3bd9800 100644 --- a/drivers/media/usb/pwc/pwc-dec23.c +++ b/drivers/media/usb/pwc/pwc-dec23.c @@ -649,11 +649,10 @@ static void DecompressBand23(struct pwc_dec23_private *pdec, } /** - * * Uncompress a pwc23 buffer. - * - * src: raw data - * dst: image output + * @pdev: pointer to pwc device's internal struct + * @src: raw data + * @dst: image output */ void pwc_dec23_decompress(struct pwc_device *pdev, const void *src, diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index eb6921d2743e..54b036d39c5b 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -262,7 +262,8 @@ static void pwc_isoc_handler(struct urb *urb) if (urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN) { - PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); + PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronously.\n", + urb, urb->status == -ENOENT ? "" : "a"); return; } diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index b2f239c4ba42..7fee5766587a 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -485,9 +485,10 @@ static void s2255_reset_dsppower(struct s2255_dev *dev) /* kickstarts the firmware loading. from probe */ -static void s2255_timer(unsigned long user_data) +static void s2255_timer(struct timer_list *t) { - struct s2255_fw *data = (struct s2255_fw *)user_data; + struct s2255_dev *dev = from_timer(dev, t, timer); + struct s2255_fw *data = dev->fw_data; if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) { pr_err("s2255: can't submit urb\n"); atomic_set(&data->fw_state, S2255_FW_FAILED); @@ -2283,7 +2284,7 @@ static int s2255_probe(struct usb_interface *interface, dev_err(&interface->dev, "Could not find bulk-in endpoint\n"); goto errorEP; } - setup_timer(&dev->timer, s2255_timer, (unsigned long)dev->fw_data); + timer_setup(&dev->timer, s2255_timer, 0); init_waitqueue_head(&dev->fw_data->wait_fw); for (i = 0; i < MAX_CHANNELS; i++) { struct s2255_vc *vc = &dev->vc[i]; diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 8c1f926567ec..d07349cf9489 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -74,7 +74,7 @@ struct smsusb_device_t { static int smsusb_submit_urb(struct smsusb_device_t *dev, struct smsusb_urb_t *surb); -/** +/* * Completing URB's callback handler - bottom half (proccess context) * submits the URB prepared on smsusb_onresponse() */ @@ -86,7 +86,7 @@ static void do_submit_urb(struct work_struct *work) smsusb_submit_urb(dev, surb); } -/** +/* * Completing URB's callback handler - top half (interrupt context) * adds completing sms urb to the global surbs list and activtes the worker * thread the surb diff --git a/drivers/media/usb/stk1160/stk1160-i2c.c b/drivers/media/usb/stk1160/stk1160-i2c.c index 2c70173e3c82..62a12d5356ad 100644 --- a/drivers/media/usb/stk1160/stk1160-i2c.c +++ b/drivers/media/usb/stk1160/stk1160-i2c.c @@ -246,7 +246,7 @@ static const struct i2c_adapter adap_template = { .algo = &algo, }; -static struct i2c_client client_template = { +static const struct i2c_client client_template = { .name = "stk1160 internal", }; diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index ce8ebbe395a6..423c03a0638d 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -38,10 +38,10 @@ static inline void print_err_status(struct stk1160 *dev, switch (status) { case -ENOENT: - errmsg = "unlinked synchronuously"; + errmsg = "unlinked synchronously"; break; case -ECONNRESET: - errmsg = "unlinked asynchronuously"; + errmsg = "unlinked asynchronously"; break; case -ENOSR: errmsg = "Buffer error (overrun)"; diff --git a/drivers/media/usb/tm6000/tm6000-cards.c b/drivers/media/usb/tm6000/tm6000-cards.c index 2537643a1808..77347541904d 100644 --- a/drivers/media/usb/tm6000/tm6000-cards.c +++ b/drivers/media/usb/tm6000/tm6000-cards.c @@ -1184,7 +1184,7 @@ static int tm6000_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_device *usbdev; - struct tm6000_core *dev = NULL; + struct tm6000_core *dev; int i, rc = 0; int nr = 0; char *speed; @@ -1194,22 +1194,21 @@ static int tm6000_usb_probe(struct usb_interface *interface, /* Selects the proper interface */ rc = usb_set_interface(usbdev, 0, 1); if (rc < 0) - goto err; + goto report_failure; /* Check to see next free device and mark as used */ nr = find_first_zero_bit(&tm6000_devused, TM6000_MAXBOARDS); if (nr >= TM6000_MAXBOARDS) { printk(KERN_ERR "tm6000: Supports only %i tm60xx boards.\n", TM6000_MAXBOARDS); - usb_put_dev(usbdev); - return -ENOMEM; + rc = -ENOMEM; + goto put_device; } /* Create and initialize dev struct */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - printk(KERN_ERR "tm6000" ": out of memory!\n"); - usb_put_dev(usbdev); - return -ENOMEM; + if (!dev) { + rc = -ENOMEM; + goto put_device; } spin_lock_init(&dev->slock); mutex_init(&dev->usb_lock); @@ -1313,8 +1312,7 @@ static int tm6000_usb_probe(struct usb_interface *interface, if (!dev->isoc_in.endp) { printk(KERN_ERR "tm6000: probing error: no IN ISOC endpoint!\n"); rc = -ENODEV; - - goto err; + goto free_device; } /* save our data pointer in this interface device */ @@ -1324,17 +1322,18 @@ static int tm6000_usb_probe(struct usb_interface *interface, rc = tm6000_init_dev(dev); if (rc < 0) - goto err; + goto free_device; return 0; -err: +free_device: + kfree(dev); +report_failure: printk(KERN_ERR "tm6000: Error %d while registering\n", rc); clear_bit(nr, &tm6000_devused); +put_device: usb_put_dev(usbdev); - - kfree(dev); return rc; } diff --git a/drivers/media/usb/tm6000/tm6000-dvb.c b/drivers/media/usb/tm6000/tm6000-dvb.c index 097ac321b7e1..c811fc6cf48a 100644 --- a/drivers/media/usb/tm6000/tm6000-dvb.c +++ b/drivers/media/usb/tm6000/tm6000-dvb.c @@ -45,10 +45,10 @@ static inline void print_err_status(struct tm6000_core *dev, switch (status) { case -ENOENT: - errmsg = "unlinked synchronuously"; + errmsg = "unlinked synchronously"; break; case -ECONNRESET: - errmsg = "unlinked asynchronuously"; + errmsg = "unlinked asynchronously"; break; case -ENOSR: errmsg = "Buffer error (overrun)"; @@ -123,7 +123,7 @@ static int tm6000_start_stream(struct tm6000_core *dev) } dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); - if (dvb->bulk_urb == NULL) + if (!dvb->bulk_urb) return -ENOMEM; pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress @@ -133,9 +133,8 @@ static int tm6000_start_stream(struct tm6000_core *dev) size = size * 15; /* 512 x 8 or 12 or 15 */ dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); - if (dvb->bulk_urb->transfer_buffer == NULL) { + if (!dvb->bulk_urb->transfer_buffer) { usb_free_urb(dvb->bulk_urb); - printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n"); return -ENOMEM; } @@ -361,7 +360,7 @@ static void unregister_dvb(struct tm6000_core *dev) { struct tm6000_dvb *dvb = dev->dvb; - if (dvb->bulk_urb != NULL) { + if (dvb->bulk_urb) { struct urb *bulk_urb = dvb->bulk_urb; kfree(bulk_urb->transfer_buffer); @@ -400,10 +399,8 @@ static int dvb_init(struct tm6000_core *dev) } dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL); - if (!dvb) { - printk(KERN_INFO "Cannot allocate memory\n"); + if (!dvb) return -ENOMEM; - } dev->dvb = dvb; diff --git a/drivers/media/usb/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c index 91889ad9cdd7..397990afe00b 100644 --- a/drivers/media/usb/tm6000/tm6000-input.c +++ b/drivers/media/usb/tm6000/tm6000-input.c @@ -352,7 +352,7 @@ static int __tm6000_ir_int_start(struct rc_dev *rc) dprintk(1, "IR max size: %d\n", size); ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC); - if (ir->int_urb->transfer_buffer == NULL) { + if (!ir->int_urb->transfer_buffer) { usb_free_urb(ir->int_urb); return err; } diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index ec8c4d2534dc..9fa25de6b5a9 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -342,10 +342,10 @@ static inline void print_err_status(struct tm6000_core *dev, switch (status) { case -ENOENT: - errmsg = "unlinked synchronuously"; + errmsg = "unlinked synchronously"; break; case -ECONNRESET: - errmsg = "unlinked asynchronuously"; + errmsg = "unlinked asynchronously"; break; case -ENOSR: errmsg = "Buffer error (overrun)"; @@ -470,20 +470,16 @@ static int tm6000_alloc_urb_buffers(struct tm6000_core *dev) int num_bufs = TM6000_NUM_URB_BUF; int i; - if (dev->urb_buffer != NULL) + if (dev->urb_buffer) return 0; dev->urb_buffer = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); - if (!dev->urb_buffer) { - tm6000_err("cannot allocate memory for urb buffers\n"); + if (!dev->urb_buffer) return -ENOMEM; - } dev->urb_dma = kmalloc(sizeof(dma_addr_t *)*num_bufs, GFP_KERNEL); - if (!dev->urb_dma) { - tm6000_err("cannot allocate memory for urb dma pointers\n"); + if (!dev->urb_dma) return -ENOMEM; - } for (i = 0; i < num_bufs; i++) { dev->urb_buffer[i] = usb_alloc_coherent( @@ -507,7 +503,7 @@ static int tm6000_free_urb_buffers(struct tm6000_core *dev) { int i; - if (dev->urb_buffer == NULL) + if (!dev->urb_buffer) return 0; for (i = 0; i < TM6000_NUM_URB_BUF; i++) { @@ -598,15 +594,12 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev) dev->isoc_ctl.num_bufs = num_bufs; dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); - if (!dev->isoc_ctl.urb) { - tm6000_err("cannot alloc memory for usb buffers\n"); + if (!dev->isoc_ctl.urb) return -ENOMEM; - } dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); if (!dev->isoc_ctl.transfer_buffer) { - tm6000_err("cannot allocate memory for usbtransfer\n"); kfree(dev->isoc_ctl.urb); return -ENOMEM; } diff --git a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c index b842f367249f..a142b9dc0feb 100644 --- a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c @@ -76,7 +76,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define TTUSB_REV_2_2 0x22 #define TTUSB_BUDGET_NAME "ttusb_stc_fw" -/** +/* * since we're casting (struct ttusb*) <-> (struct dvb_demux*) around * the dvb_demux field must be the first in struct!! */ @@ -713,7 +713,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) } } - /** + /* * if length is valid and we reached the end: * goto next muxpack */ @@ -729,7 +729,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) /* maximum bytes, until we know the length */ ttusb->muxpack_len = 2; - /** + /* * no muxpacks left? * return to search-sync state */ diff --git a/drivers/media/usb/usbtv/usbtv-core.c b/drivers/media/usb/usbtv/usbtv-core.c index f06f09a0876e..127f8a0c098b 100644 --- a/drivers/media/usb/usbtv/usbtv-core.c +++ b/drivers/media/usb/usbtv/usbtv-core.c @@ -84,7 +84,7 @@ static int usbtv_probe(struct usb_interface *intf, /* Packet size is split into 11 bits of base size and count of * extra multiplies of it.*/ size = usb_endpoint_maxp(&ep->desc); - size = (size & 0x07ff) * usb_endpoint_maxp_mult(&ep->desc); + size = size * usb_endpoint_maxp_mult(&ep->desc); /* Device structure */ usbtv = kzalloc(sizeof(struct usbtv), GFP_KERNEL); @@ -144,6 +144,7 @@ static void usbtv_disconnect(struct usb_interface *intf) static const struct usb_device_id usbtv_id_table[] = { { USB_DEVICE(0x1b71, 0x3002) }, + { USB_DEVICE(0x1f71, 0x3301) }, {} }; MODULE_DEVICE_TABLE(usb, usbtv_id_table); diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 95b5f4319ec2..3668a04359e8 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -718,8 +718,8 @@ static int usbtv_s_ctrl(struct v4l2_ctrl *ctrl) */ if (ctrl->id == V4L2_CID_BRIGHTNESS || ctrl->id == V4L2_CID_CONTRAST) { ret = usb_control_msg(usbtv->udev, - usb_sndctrlpipe(usbtv->udev, 0), USBTV_CONTROL_REG, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + usb_rcvctrlpipe(usbtv->udev, 0), USBTV_CONTROL_REG, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, USBTV_BASE + 0x0244, (void *)data, 3, 0); if (ret < 0) goto error; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 6d22b22cb35b..28b91b7d756f 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2230,7 +2230,7 @@ static int uvc_reset_resume(struct usb_interface *intf) * Module parameters */ -static int uvc_clock_param_get(char *buffer, struct kernel_param *kp) +static int uvc_clock_param_get(char *buffer, const struct kernel_param *kp) { if (uvc_clock_param == CLOCK_MONOTONIC) return sprintf(buffer, "CLOCK_MONOTONIC"); @@ -2238,7 +2238,7 @@ static int uvc_clock_param_get(char *buffer, struct kernel_param *kp) return sprintf(buffer, "CLOCK_REALTIME"); } -static int uvc_clock_param_set(const char *val, struct kernel_param *kp) +static int uvc_clock_param_set(const char *val, const struct kernel_param *kp) { if (strncasecmp(val, "clock_", strlen("clock_")) == 0) val += strlen("clock_"); diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index 4ff8d0aed015..1d888661fd03 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -209,10 +209,8 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value, int status; unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL); - if (!transfer_buffer) { - dev_err(&udev->dev, "kmalloc(%d) failed\n", size); + if (!transfer_buffer) return -ENOMEM; - } memcpy(transfer_buffer, cp, size); @@ -387,9 +385,9 @@ static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, vb); int rc; - DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ? - cam->fmt->name : ""); - if (cam->fmt == NULL) + DBG("%s, field=%d, fmt name = %s\n", __func__, field, + cam->fmt ? cam->fmt->name : ""); + if (!cam->fmt) return -EINVAL; buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3); @@ -789,7 +787,7 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct zr364xx_camera *cam = video_drvdata(file); char pixelformat_name[5]; - if (cam == NULL) + if (!cam) return -ENODEV; if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) { @@ -819,7 +817,7 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, { struct zr364xx_camera *cam; - if (file == NULL) + if (!file) return -ENODEV; cam = video_drvdata(file); @@ -981,13 +979,13 @@ static void read_pipe_completion(struct urb *purb) pipe_info = purb->context; _DBG("%s %p, status %d\n", __func__, purb, purb->status); - if (pipe_info == NULL) { + if (!pipe_info) { printk(KERN_ERR KBUILD_MODNAME ": no context!\n"); return; } cam = pipe_info->cam; - if (cam == NULL) { + if (!cam) { printk(KERN_ERR KBUILD_MODNAME ": no context!\n"); return; } @@ -1071,7 +1069,7 @@ static void zr364xx_stop_readpipe(struct zr364xx_camera *cam) { struct zr364xx_pipeinfo *pipe_info; - if (cam == NULL) { + if (!cam) { printk(KERN_ERR KBUILD_MODNAME ": invalid device\n"); return; } @@ -1275,7 +1273,7 @@ static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma) struct zr364xx_camera *cam = video_drvdata(file); int ret; - if (cam == NULL) { + if (!cam) { DBG("%s: cam == NULL\n", __func__); return -ENODEV; } @@ -1359,7 +1357,7 @@ static int zr364xx_board_init(struct zr364xx_camera *cam) pipe->transfer_buffer = kzalloc(pipe->transfer_size, GFP_KERNEL); - if (pipe->transfer_buffer == NULL) { + if (!pipe->transfer_buffer) { DBG("out of memory!\n"); return -ENOMEM; } @@ -1375,7 +1373,7 @@ static int zr364xx_board_init(struct zr364xx_camera *cam) DBG("valloc %p, idx %lu, pdata %p\n", &cam->buffer.frame[i], i, cam->buffer.frame[i].lpvbits); - if (cam->buffer.frame[i].lpvbits == NULL) { + if (!cam->buffer.frame[i].lpvbits) { printk(KERN_INFO KBUILD_MODNAME ": out of memory. Using less frames\n"); break; } @@ -1423,11 +1421,9 @@ static int zr364xx_probe(struct usb_interface *intf, le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); - cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL); - if (cam == NULL) { - dev_err(&udev->dev, "cam: out of memory !\n"); + cam = kzalloc(sizeof(*cam), GFP_KERNEL); + if (!cam) return -ENOMEM; - } cam->v4l2_dev.release = zr364xx_release; err = v4l2_device_register(&intf->dev, &cam->v4l2_dev); diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index 8db45dfc271b..82852f23a3b6 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -239,7 +239,7 @@ static const struct analog_demod_ops tuner_analog_ops = { * @type: type of the tuner (e. g. tuner number) * @new_mode_mask: Indicates if tuner supports TV and/or Radio * @new_config: an optional parameter used by a few tuners to adjust - internal parameters, like LNA mode + * internal parameters, like LNA mode * @tuner_callback: an optional function to be called when switching * to analog mode * @@ -750,6 +750,7 @@ static int tuner_remove(struct i2c_client *client) /** * check_mode - Verify if tuner supports the requested mode * @t: a pointer to the module's internal struct_tuner + * @mode: mode of the tuner, as defined by &enum v4l2_tuner_type. * * This function checks if the tuner is capable of tuning analog TV, * digital TV or radio, depending on what the caller wants. If the @@ -757,6 +758,7 @@ static int tuner_remove(struct i2c_client *client) * returns 0. * This function is needed for boards that have a separate tuner for * radio (like devices with tea5767). + * * NOTE: mt20xx uses V4L2_TUNER_DIGITAL_TV and calls set_tv_freq to * select a TV frequency. So, t_mode = T_ANALOG_TV could actually * be used to represent a Digital TV too. diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index d741a8e0fdac..e5acfab470a5 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -22,8 +22,37 @@ #include <media/v4l2-async.h> #include <media/v4l2-device.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> +static int v4l2_async_notifier_call_bound(struct v4l2_async_notifier *n, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd) +{ + if (!n->ops || !n->ops->bound) + return 0; + + return n->ops->bound(n, subdev, asd); +} + +static void v4l2_async_notifier_call_unbind(struct v4l2_async_notifier *n, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd) +{ + if (!n->ops || !n->ops->unbind) + return; + + n->ops->unbind(n, subdev, asd); +} + +static int v4l2_async_notifier_call_complete(struct v4l2_async_notifier *n) +{ + if (!n->ops || !n->ops->complete) + return 0; + + return n->ops->complete(n); +} + static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) { #if IS_ENABLED(CONFIG_I2C) @@ -60,8 +89,8 @@ static LIST_HEAD(subdev_list); static LIST_HEAD(notifier_list); static DEFINE_MUTEX(list_lock); -static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *sd) +static struct v4l2_async_subdev *v4l2_async_find_match( + struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd) { bool (*match)(struct v4l2_subdev *, struct v4l2_async_subdev *); struct v4l2_async_subdev *asd; @@ -95,22 +124,96 @@ static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier * return NULL; } -static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) +/* Find the sub-device notifier registered by a sub-device driver. */ +static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier( + struct v4l2_subdev *sd) { - int ret; + struct v4l2_async_notifier *n; - if (notifier->bound) { - ret = notifier->bound(notifier, sd, asd); - if (ret < 0) - return ret; + list_for_each_entry(n, ¬ifier_list, list) + if (n->sd == sd) + return n; + + return NULL; +} + +/* Get v4l2_device related to the notifier if one can be found. */ +static struct v4l2_device *v4l2_async_notifier_find_v4l2_dev( + struct v4l2_async_notifier *notifier) +{ + while (notifier->parent) + notifier = notifier->parent; + + return notifier->v4l2_dev; +} + +/* + * Return true if all child sub-device notifiers are complete, false otherwise. + */ +static bool v4l2_async_notifier_can_complete( + struct v4l2_async_notifier *notifier) +{ + struct v4l2_subdev *sd; + + if (!list_empty(¬ifier->waiting)) + return false; + + list_for_each_entry(sd, ¬ifier->done, async_list) { + struct v4l2_async_notifier *subdev_notifier = + v4l2_async_find_subdev_notifier(sd); + + if (subdev_notifier && + !v4l2_async_notifier_can_complete(subdev_notifier)) + return false; } - ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd); + return true; +} + +/* + * Complete the master notifier if possible. This is done when all async + * sub-devices have been bound; v4l2_device is also available then. + */ +static int v4l2_async_notifier_try_complete( + struct v4l2_async_notifier *notifier) +{ + /* Quick check whether there are still more sub-devices here. */ + if (!list_empty(¬ifier->waiting)) + return 0; + + /* Check the entire notifier tree; find the root notifier first. */ + while (notifier->parent) + notifier = notifier->parent; + + /* This is root if it has v4l2_dev. */ + if (!notifier->v4l2_dev) + return 0; + + /* Is everything ready? */ + if (!v4l2_async_notifier_can_complete(notifier)) + return 0; + + return v4l2_async_notifier_call_complete(notifier); +} + +static int v4l2_async_notifier_try_all_subdevs( + struct v4l2_async_notifier *notifier); + +static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, + struct v4l2_device *v4l2_dev, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct v4l2_async_notifier *subdev_notifier; + int ret; + + ret = v4l2_device_register_subdev(v4l2_dev, sd); + if (ret < 0) + return ret; + + ret = v4l2_async_notifier_call_bound(notifier, sd, asd); if (ret < 0) { - if (notifier->unbind) - notifier->unbind(notifier, sd, asd); + v4l2_device_unregister_subdev(sd); return ret; } @@ -122,8 +225,55 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, /* Move from the global subdevice list to notifier's done */ list_move(&sd->async_list, ¬ifier->done); - if (list_empty(¬ifier->waiting) && notifier->complete) - return notifier->complete(notifier); + /* + * See if the sub-device has a notifier. If not, return here. + */ + subdev_notifier = v4l2_async_find_subdev_notifier(sd); + if (!subdev_notifier || subdev_notifier->parent) + return 0; + + /* + * Proceed with checking for the sub-device notifier's async + * sub-devices, and return the result. The error will be handled by the + * caller. + */ + subdev_notifier->parent = notifier; + + return v4l2_async_notifier_try_all_subdevs(subdev_notifier); +} + +/* Test all async sub-devices in a notifier for a match. */ +static int v4l2_async_notifier_try_all_subdevs( + struct v4l2_async_notifier *notifier) +{ + struct v4l2_device *v4l2_dev = + v4l2_async_notifier_find_v4l2_dev(notifier); + struct v4l2_subdev *sd; + + if (!v4l2_dev) + return 0; + +again: + list_for_each_entry(sd, &subdev_list, async_list) { + struct v4l2_async_subdev *asd; + int ret; + + asd = v4l2_async_find_match(notifier, sd); + if (!asd) + continue; + + ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd); + if (ret < 0) + return ret; + + /* + * v4l2_async_match_notify() may lead to registering a + * new notifier and thus changing the async subdevs + * list. In order to proceed safely from here, restart + * parsing the list from the beginning. + */ + goto again; + } return 0; } @@ -134,24 +284,107 @@ static void v4l2_async_cleanup(struct v4l2_subdev *sd) /* Subdevice driver will reprobe and put the subdev back onto the list */ list_del_init(&sd->async_list); sd->asd = NULL; - sd->dev = NULL; } -int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, - struct v4l2_async_notifier *notifier) +/* Unbind all sub-devices in the notifier tree. */ +static void v4l2_async_notifier_unbind_all_subdevs( + struct v4l2_async_notifier *notifier) { struct v4l2_subdev *sd, *tmp; + + list_for_each_entry_safe(sd, tmp, ¬ifier->done, async_list) { + struct v4l2_async_notifier *subdev_notifier = + v4l2_async_find_subdev_notifier(sd); + + if (subdev_notifier) + v4l2_async_notifier_unbind_all_subdevs(subdev_notifier); + + v4l2_async_notifier_call_unbind(notifier, sd, sd->asd); + v4l2_async_cleanup(sd); + + list_move(&sd->async_list, &subdev_list); + } + + notifier->parent = NULL; +} + +/* See if an fwnode can be found in a notifier's lists. */ +static bool __v4l2_async_notifier_fwnode_has_async_subdev( + struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode) +{ struct v4l2_async_subdev *asd; + struct v4l2_subdev *sd; + + list_for_each_entry(asd, ¬ifier->waiting, list) { + if (asd->match_type != V4L2_ASYNC_MATCH_FWNODE) + continue; + + if (asd->match.fwnode.fwnode == fwnode) + return true; + } + + list_for_each_entry(sd, ¬ifier->done, async_list) { + if (WARN_ON(!sd->asd)) + continue; + + if (sd->asd->match_type != V4L2_ASYNC_MATCH_FWNODE) + continue; + + if (sd->asd->match.fwnode.fwnode == fwnode) + return true; + } + + return false; +} + +/* + * Find out whether an async sub-device was set up for an fwnode already or + * whether it exists in a given notifier before @this_index. + */ +static bool v4l2_async_notifier_fwnode_has_async_subdev( + struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode, + unsigned int this_index) +{ + unsigned int j; + + lockdep_assert_held(&list_lock); + + /* Check that an fwnode is not being added more than once. */ + for (j = 0; j < this_index; j++) { + struct v4l2_async_subdev *asd = notifier->subdevs[this_index]; + struct v4l2_async_subdev *other_asd = notifier->subdevs[j]; + + if (other_asd->match_type == V4L2_ASYNC_MATCH_FWNODE && + asd->match.fwnode.fwnode == + other_asd->match.fwnode.fwnode) + return true; + } + + /* Check than an fwnode did not exist in other notifiers. */ + list_for_each_entry(notifier, ¬ifier_list, list) + if (__v4l2_async_notifier_fwnode_has_async_subdev( + notifier, fwnode)) + return true; + + return false; +} + +static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier) +{ + struct device *dev = + notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL; + struct v4l2_async_subdev *asd; + int ret; int i; - if (!v4l2_dev || !notifier->num_subdevs || - notifier->num_subdevs > V4L2_MAX_SUBDEVS) + if (notifier->num_subdevs > V4L2_MAX_SUBDEVS) return -EINVAL; - notifier->v4l2_dev = v4l2_dev; INIT_LIST_HEAD(¬ifier->waiting); INIT_LIST_HEAD(¬ifier->done); + mutex_lock(&list_lock); + for (i = 0; i < notifier->num_subdevs; i++) { asd = notifier->subdevs[i]; @@ -159,32 +392,32 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, case V4L2_ASYNC_MATCH_CUSTOM: case V4L2_ASYNC_MATCH_DEVNAME: case V4L2_ASYNC_MATCH_I2C: + break; case V4L2_ASYNC_MATCH_FWNODE: + if (v4l2_async_notifier_fwnode_has_async_subdev( + notifier, asd->match.fwnode.fwnode, i)) { + dev_err(dev, + "fwnode has already been registered or in notifier's subdev list\n"); + ret = -EEXIST; + goto err_unlock; + } break; default: - dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL, - "Invalid match type %u on %p\n", + dev_err(dev, "Invalid match type %u on %p\n", asd->match_type, asd); - return -EINVAL; + ret = -EINVAL; + goto err_unlock; } list_add_tail(&asd->list, ¬ifier->waiting); } - mutex_lock(&list_lock); + ret = v4l2_async_notifier_try_all_subdevs(notifier); + if (ret < 0) + goto err_unbind; - list_for_each_entry_safe(sd, tmp, &subdev_list, async_list) { - int ret; - - asd = v4l2_async_belongs(notifier, sd); - if (!asd) - continue; - - ret = v4l2_async_test_notify(notifier, sd, asd); - if (ret < 0) { - mutex_unlock(&list_lock); - return ret; - } - } + ret = v4l2_async_notifier_try_complete(notifier); + if (ret < 0) + goto err_unbind; /* Keep also completed notifiers on the list */ list_add(¬ifier->list, ¬ifier_list); @@ -192,90 +425,114 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, mutex_unlock(&list_lock); return 0; + +err_unbind: + /* + * On failure, unbind all sub-devices registered through this notifier. + */ + v4l2_async_notifier_unbind_all_subdevs(notifier); + +err_unlock: + mutex_unlock(&list_lock); + + return ret; +} + +int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, + struct v4l2_async_notifier *notifier) +{ + int ret; + + if (WARN_ON(!v4l2_dev || notifier->sd)) + return -EINVAL; + + notifier->v4l2_dev = v4l2_dev; + + ret = __v4l2_async_notifier_register(notifier); + if (ret) + notifier->v4l2_dev = NULL; + + return ret; } EXPORT_SYMBOL(v4l2_async_notifier_register); -void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) +int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd, + struct v4l2_async_notifier *notifier) { - struct v4l2_subdev *sd, *tmp; - unsigned int notif_n_subdev = notifier->num_subdevs; - unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS); - struct device **dev; - int i = 0; + int ret; - if (!notifier->v4l2_dev) - return; + if (WARN_ON(!sd || notifier->v4l2_dev)) + return -EINVAL; - dev = kvmalloc_array(n_subdev, sizeof(*dev), GFP_KERNEL); - if (!dev) { - dev_err(notifier->v4l2_dev->dev, - "Failed to allocate device cache!\n"); - } + notifier->sd = sd; - mutex_lock(&list_lock); + ret = __v4l2_async_notifier_register(notifier); + if (ret) + notifier->sd = NULL; - list_del(¬ifier->list); + return ret; +} +EXPORT_SYMBOL(v4l2_async_subdev_notifier_register); - list_for_each_entry_safe(sd, tmp, ¬ifier->done, async_list) { - struct device *d; +static void __v4l2_async_notifier_unregister( + struct v4l2_async_notifier *notifier) +{ + if (!notifier || (!notifier->v4l2_dev && !notifier->sd)) + return; - d = get_device(sd->dev); + v4l2_async_notifier_unbind_all_subdevs(notifier); - v4l2_async_cleanup(sd); + notifier->sd = NULL; + notifier->v4l2_dev = NULL; - /* If we handled USB devices, we'd have to lock the parent too */ - device_release_driver(d); + list_del(¬ifier->list); +} - if (notifier->unbind) - notifier->unbind(notifier, sd, sd->asd); +void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) +{ + mutex_lock(&list_lock); - /* - * Store device at the device cache, in order to call - * put_device() on the final step - */ - if (dev) - dev[i++] = d; - else - put_device(d); - } + __v4l2_async_notifier_unregister(notifier); mutex_unlock(&list_lock); +} +EXPORT_SYMBOL(v4l2_async_notifier_unregister); - /* - * Call device_attach() to reprobe devices - * - * NOTE: If dev allocation fails, i is 0, and the whole loop won't be - * executed. - */ - while (i--) { - struct device *d = dev[i]; - - if (d && device_attach(d) < 0) { - const char *name = "(none)"; - int lock = device_trylock(d); - - if (lock && d->driver) - name = d->driver->name; - dev_err(d, "Failed to re-probe to %s\n", name); - if (lock) - device_unlock(d); +void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier) +{ + unsigned int i; + + if (!notifier || !notifier->max_subdevs) + return; + + for (i = 0; i < notifier->num_subdevs; i++) { + struct v4l2_async_subdev *asd = notifier->subdevs[i]; + + switch (asd->match_type) { + case V4L2_ASYNC_MATCH_FWNODE: + fwnode_handle_put(asd->match.fwnode.fwnode); + break; + default: + WARN_ON_ONCE(true); + break; } - put_device(d); + + kfree(asd); } - kvfree(dev); - notifier->v4l2_dev = NULL; + notifier->max_subdevs = 0; + notifier->num_subdevs = 0; - /* - * Don't care about the waiting list, it is initialised and populated - * upon notifier registration. - */ + kvfree(notifier->subdevs); + notifier->subdevs = NULL; } -EXPORT_SYMBOL(v4l2_async_notifier_unregister); +EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup); int v4l2_async_register_subdev(struct v4l2_subdev *sd) { + struct v4l2_async_notifier *subdev_notifier; struct v4l2_async_notifier *notifier; + int ret; /* * No reference taken. The reference is held by the device @@ -290,41 +547,73 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd) INIT_LIST_HEAD(&sd->async_list); list_for_each_entry(notifier, ¬ifier_list, list) { - struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, sd); - if (asd) { - int ret = v4l2_async_test_notify(notifier, sd, asd); - mutex_unlock(&list_lock); - return ret; - } + struct v4l2_device *v4l2_dev = + v4l2_async_notifier_find_v4l2_dev(notifier); + struct v4l2_async_subdev *asd; + + if (!v4l2_dev) + continue; + + asd = v4l2_async_find_match(notifier, sd); + if (!asd) + continue; + + ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd); + if (ret) + goto err_unbind; + + ret = v4l2_async_notifier_try_complete(notifier); + if (ret) + goto err_unbind; + + goto out_unlock; } /* None matched, wait for hot-plugging */ list_add(&sd->async_list, &subdev_list); +out_unlock: mutex_unlock(&list_lock); return 0; + +err_unbind: + /* + * Complete failed. Unbind the sub-devices bound through registering + * this async sub-device. + */ + subdev_notifier = v4l2_async_find_subdev_notifier(sd); + if (subdev_notifier) + v4l2_async_notifier_unbind_all_subdevs(subdev_notifier); + + if (sd->asd) + v4l2_async_notifier_call_unbind(notifier, sd, sd->asd); + v4l2_async_cleanup(sd); + + mutex_unlock(&list_lock); + + return ret; } EXPORT_SYMBOL(v4l2_async_register_subdev); void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) { - struct v4l2_async_notifier *notifier = sd->notifier; + mutex_lock(&list_lock); - if (!sd->asd) { - if (!list_empty(&sd->async_list)) - v4l2_async_cleanup(sd); - return; - } + __v4l2_async_notifier_unregister(sd->subdev_notifier); + v4l2_async_notifier_cleanup(sd->subdev_notifier); + kfree(sd->subdev_notifier); + sd->subdev_notifier = NULL; - mutex_lock(&list_lock); + if (sd->asd) { + struct v4l2_async_notifier *notifier = sd->notifier; - list_add(&sd->asd->list, ¬ifier->waiting); + list_add(&sd->asd->list, ¬ifier->waiting); - v4l2_async_cleanup(sd); + v4l2_async_notifier_call_unbind(notifier, sd, sd->asd); + } - if (notifier->unbind) - notifier->unbind(notifier, sd, sd->asd); + v4l2_async_cleanup(sd); mutex_unlock(&list_lock); } diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index dd1db678718c..cbb2ef43945f 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1227,6 +1227,16 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, } EXPORT_SYMBOL(v4l2_ctrl_fill); +static u32 user_flags(const struct v4l2_ctrl *ctrl) +{ + u32 flags = ctrl->flags; + + if (ctrl->is_ptr) + flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD; + + return flags; +} + static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes) { memset(ev->reserved, 0, sizeof(ev->reserved)); @@ -1234,7 +1244,7 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change ev->id = ctrl->id; ev->u.ctrl.changes = changes; ev->u.ctrl.type = ctrl->type; - ev->u.ctrl.flags = ctrl->flags; + ev->u.ctrl.flags = user_flags(ctrl); if (ctrl->is_ptr) ev->u.ctrl.value64 = 0; else @@ -2003,10 +2013,6 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, handler_set_err(hdl, err); return NULL; } - if (type == V4L2_CTRL_TYPE_BITMASK && ((def & ~max) || min || step)) { - handler_set_err(hdl, -ERANGE); - return NULL; - } if (is_array && (type == V4L2_CTRL_TYPE_BUTTON || type == V4L2_CTRL_TYPE_CTRL_CLASS)) { @@ -2577,10 +2583,8 @@ int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctr else qc->id = ctrl->id; strlcpy(qc->name, ctrl->name, sizeof(qc->name)); - qc->flags = ctrl->flags; + qc->flags = user_flags(ctrl); qc->type = ctrl->type; - if (ctrl->is_ptr) - qc->flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD; qc->elem_size = ctrl->elem_size; qc->elems = ctrl->elems; qc->nr_of_dims = ctrl->nr_of_dims; @@ -2818,7 +2822,7 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, static int class_check(struct v4l2_ctrl_handler *hdl, u32 which) { if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL) - return list_empty(&hdl->ctrl_refs) ? -EINVAL : 0; + return 0; return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL; } diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index 5c8c49d240d1..930f9c53a64e 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -245,11 +245,11 @@ EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cea861_vic); /** * v4l2_match_dv_timings - check if two timings match - * @t1 - compare this v4l2_dv_timings struct... - * @t2 - with this struct. - * @pclock_delta - the allowed pixelclock deviation. - * @match_reduced_fps - if true, then fail if V4L2_DV_FL_REDUCED_FPS does not - * match. + * @t1: compare this v4l2_dv_timings struct... + * @t2: with this struct. + * @pclock_delta: the allowed pixelclock deviation. + * @match_reduced_fps: if true, then fail if V4L2_DV_FL_REDUCED_FPS does not + * match. * * Compare t1 with t2 with a given margin of error for the pixelclock. */ diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 40b2fbfe8865..fb72c7ac04d4 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -19,6 +19,7 @@ */ #include <linux/acpi.h> #include <linux/kernel.h> +#include <linux/mm.h> #include <linux/module.h> #include <linux/of.h> #include <linux/property.h> @@ -26,7 +27,9 @@ #include <linux/string.h> #include <linux/types.h> +#include <media/v4l2-async.h> #include <media/v4l2-fwnode.h> +#include <media/v4l2-subdev.h> enum v4l2_fwnode_bus_type { V4L2_FWNODE_BUS_TYPE_GUESS = 0, @@ -181,25 +184,6 @@ v4l2_fwnode_endpoint_parse_csi1_bus(struct fwnode_handle *fwnode, vep->bus_type = V4L2_MBUS_CSI1; } -/** - * v4l2_fwnode_endpoint_parse() - parse all fwnode node properties - * @fwnode: pointer to the endpoint's fwnode handle - * @vep: pointer to the V4L2 fwnode data structure - * - * All properties are optional. If none are found, we don't set any flags. This - * means the port has a static configuration and no properties have to be - * specified explicitly. If any properties that identify the bus as parallel - * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if - * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we - * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a - * reference to @fwnode. - * - * NOTE: This function does not parse properties the size of which is variable - * without a low fixed limit. Please use v4l2_fwnode_endpoint_alloc_parse() in - * new drivers instead. - * - * Return: 0 on success or a negative error code on failure. - */ int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep) { @@ -239,14 +223,6 @@ int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode, } EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_parse); -/* - * v4l2_fwnode_endpoint_free() - free the V4L2 fwnode acquired by - * v4l2_fwnode_endpoint_alloc_parse() - * @vep - the V4L2 fwnode the resources of which are to be released - * - * It is safe to call this function with NULL argument or on a V4L2 fwnode the - * parsing of which failed. - */ void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep) { if (IS_ERR_OR_NULL(vep)) @@ -257,29 +233,6 @@ void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep) } EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_free); -/** - * v4l2_fwnode_endpoint_alloc_parse() - parse all fwnode node properties - * @fwnode: pointer to the endpoint's fwnode handle - * - * All properties are optional. If none are found, we don't set any flags. This - * means the port has a static configuration and no properties have to be - * specified explicitly. If any properties that identify the bus as parallel - * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if - * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we - * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a - * reference to @fwnode. - * - * v4l2_fwnode_endpoint_alloc_parse() has two important differences to - * v4l2_fwnode_endpoint_parse(): - * - * 1. It also parses variable size data. - * - * 2. The memory it has allocated to store the variable size data must be freed - * using v4l2_fwnode_endpoint_free() when no longer needed. - * - * Return: Pointer to v4l2_fwnode_endpoint if successful, on an error pointer - * on error. - */ struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse( struct fwnode_handle *fwnode) { @@ -322,24 +275,6 @@ out_err: } EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse); -/** - * v4l2_fwnode_endpoint_parse_link() - parse a link between two endpoints - * @__fwnode: pointer to the endpoint's fwnode at the local end of the link - * @link: pointer to the V4L2 fwnode link data structure - * - * Fill the link structure with the local and remote nodes and port numbers. - * The local_node and remote_node fields are set to point to the local and - * remote port's parent nodes respectively (the port parent node being the - * parent node of the port node if that node isn't a 'ports' node, or the - * grand-parent node of the port node otherwise). - * - * A reference is taken to both the local and remote nodes, the caller must use - * v4l2_fwnode_endpoint_put_link() to drop the references when done with the - * link. - * - * Return: 0 on success, or -ENOLINK if the remote endpoint fwnode can't be - * found. - */ int v4l2_fwnode_parse_link(struct fwnode_handle *__fwnode, struct v4l2_fwnode_link *link) { @@ -374,13 +309,6 @@ int v4l2_fwnode_parse_link(struct fwnode_handle *__fwnode, } EXPORT_SYMBOL_GPL(v4l2_fwnode_parse_link); -/** - * v4l2_fwnode_put_link() - drop references to nodes in a link - * @link: pointer to the V4L2 fwnode link data structure - * - * Drop references to the local and remote nodes in the link. This function - * must be called on every link parsed with v4l2_fwnode_parse_link(). - */ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link) { fwnode_handle_put(link->local_node); @@ -388,6 +316,630 @@ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link) } EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link); +static int v4l2_async_notifier_realloc(struct v4l2_async_notifier *notifier, + unsigned int max_subdevs) +{ + struct v4l2_async_subdev **subdevs; + + if (max_subdevs <= notifier->max_subdevs) + return 0; + + subdevs = kvmalloc_array( + max_subdevs, sizeof(*notifier->subdevs), + GFP_KERNEL | __GFP_ZERO); + if (!subdevs) + return -ENOMEM; + + if (notifier->subdevs) { + memcpy(subdevs, notifier->subdevs, + sizeof(*subdevs) * notifier->num_subdevs); + + kvfree(notifier->subdevs); + } + + notifier->subdevs = subdevs; + notifier->max_subdevs = max_subdevs; + + return 0; +} + +static int v4l2_async_notifier_fwnode_parse_endpoint( + struct device *dev, struct v4l2_async_notifier *notifier, + struct fwnode_handle *endpoint, unsigned int asd_struct_size, + int (*parse_endpoint)(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd)) +{ + struct v4l2_async_subdev *asd; + struct v4l2_fwnode_endpoint *vep; + int ret = 0; + + asd = kzalloc(asd_struct_size, GFP_KERNEL); + if (!asd) + return -ENOMEM; + + asd->match_type = V4L2_ASYNC_MATCH_FWNODE; + asd->match.fwnode.fwnode = + fwnode_graph_get_remote_port_parent(endpoint); + if (!asd->match.fwnode.fwnode) { + dev_warn(dev, "bad remote port parent\n"); + ret = -EINVAL; + goto out_err; + } + + vep = v4l2_fwnode_endpoint_alloc_parse(endpoint); + if (IS_ERR(vep)) { + ret = PTR_ERR(vep); + dev_warn(dev, "unable to parse V4L2 fwnode endpoint (%d)\n", + ret); + goto out_err; + } + + ret = parse_endpoint ? parse_endpoint(dev, vep, asd) : 0; + if (ret == -ENOTCONN) + dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep->base.port, + vep->base.id); + else if (ret < 0) + dev_warn(dev, + "driver could not parse port@%u/endpoint@%u (%d)\n", + vep->base.port, vep->base.id, ret); + v4l2_fwnode_endpoint_free(vep); + if (ret < 0) + goto out_err; + + notifier->subdevs[notifier->num_subdevs] = asd; + notifier->num_subdevs++; + + return 0; + +out_err: + fwnode_handle_put(asd->match.fwnode.fwnode); + kfree(asd); + + return ret == -ENOTCONN ? 0 : ret; +} + +static int __v4l2_async_notifier_parse_fwnode_endpoints( + struct device *dev, struct v4l2_async_notifier *notifier, + size_t asd_struct_size, unsigned int port, bool has_port, + int (*parse_endpoint)(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd)) +{ + struct fwnode_handle *fwnode; + unsigned int max_subdevs = notifier->max_subdevs; + int ret; + + if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev))) + return -EINVAL; + + for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint( + dev_fwnode(dev), fwnode)); ) { + struct fwnode_handle *dev_fwnode; + bool is_available; + + dev_fwnode = fwnode_graph_get_port_parent(fwnode); + is_available = fwnode_device_is_available(dev_fwnode); + fwnode_handle_put(dev_fwnode); + if (!is_available) + continue; + + if (has_port) { + struct fwnode_endpoint ep; + + ret = fwnode_graph_parse_endpoint(fwnode, &ep); + if (ret) { + fwnode_handle_put(fwnode); + return ret; + } + + if (ep.port != port) + continue; + } + max_subdevs++; + } + + /* No subdevs to add? Return here. */ + if (max_subdevs == notifier->max_subdevs) + return 0; + + ret = v4l2_async_notifier_realloc(notifier, max_subdevs); + if (ret) + return ret; + + for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint( + dev_fwnode(dev), fwnode)); ) { + struct fwnode_handle *dev_fwnode; + bool is_available; + + dev_fwnode = fwnode_graph_get_port_parent(fwnode); + is_available = fwnode_device_is_available(dev_fwnode); + fwnode_handle_put(dev_fwnode); + if (!is_available) + continue; + + if (has_port) { + struct fwnode_endpoint ep; + + ret = fwnode_graph_parse_endpoint(fwnode, &ep); + if (ret) + break; + + if (ep.port != port) + continue; + } + + if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) { + ret = -EINVAL; + break; + } + + ret = v4l2_async_notifier_fwnode_parse_endpoint( + dev, notifier, fwnode, asd_struct_size, parse_endpoint); + if (ret < 0) + break; + } + + fwnode_handle_put(fwnode); + + return ret; +} + +int v4l2_async_notifier_parse_fwnode_endpoints( + struct device *dev, struct v4l2_async_notifier *notifier, + size_t asd_struct_size, + int (*parse_endpoint)(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd)) +{ + return __v4l2_async_notifier_parse_fwnode_endpoints( + dev, notifier, asd_struct_size, 0, false, parse_endpoint); +} +EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints); + +int v4l2_async_notifier_parse_fwnode_endpoints_by_port( + struct device *dev, struct v4l2_async_notifier *notifier, + size_t asd_struct_size, unsigned int port, + int (*parse_endpoint)(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd)) +{ + return __v4l2_async_notifier_parse_fwnode_endpoints( + dev, notifier, asd_struct_size, port, true, parse_endpoint); +} +EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port); + +/* + * v4l2_fwnode_reference_parse - parse references for async sub-devices + * @dev: the device node the properties of which are parsed for references + * @notifier: the async notifier where the async subdevs will be added + * @prop: the name of the property + * + * Return: 0 on success + * -ENOENT if no entries were found + * -ENOMEM if memory allocation failed + * -EINVAL if property parsing failed + */ +static int v4l2_fwnode_reference_parse( + struct device *dev, struct v4l2_async_notifier *notifier, + const char *prop) +{ + struct fwnode_reference_args args; + unsigned int index; + int ret; + + for (index = 0; + !(ret = fwnode_property_get_reference_args( + dev_fwnode(dev), prop, NULL, 0, index, &args)); + index++) + fwnode_handle_put(args.fwnode); + + if (!index) + return -ENOENT; + + /* + * Note that right now both -ENODATA and -ENOENT may signal + * out-of-bounds access. Return the error in cases other than that. + */ + if (ret != -ENOENT && ret != -ENODATA) + return ret; + + ret = v4l2_async_notifier_realloc(notifier, + notifier->num_subdevs + index); + if (ret) + return ret; + + for (index = 0; !fwnode_property_get_reference_args( + dev_fwnode(dev), prop, NULL, 0, index, &args); + index++) { + struct v4l2_async_subdev *asd; + + if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) { + ret = -EINVAL; + goto error; + } + + asd = kzalloc(sizeof(*asd), GFP_KERNEL); + if (!asd) { + ret = -ENOMEM; + goto error; + } + + notifier->subdevs[notifier->num_subdevs] = asd; + asd->match.fwnode.fwnode = args.fwnode; + asd->match_type = V4L2_ASYNC_MATCH_FWNODE; + notifier->num_subdevs++; + } + + return 0; + +error: + fwnode_handle_put(args.fwnode); + return ret; +} + +/* + * v4l2_fwnode_reference_get_int_prop - parse a reference with integer + * arguments + * @fwnode: fwnode to read @prop from + * @notifier: notifier for @dev + * @prop: the name of the property + * @index: the index of the reference to get + * @props: the array of integer property names + * @nprops: the number of integer property names in @nprops + * + * First find an fwnode referred to by the reference at @index in @prop. + * + * Then under that fwnode, @nprops times, for each property in @props, + * iteratively follow child nodes starting from fwnode such that they have the + * property in @props array at the index of the child node distance from the + * root node and the value of that property matching with the integer argument + * of the reference, at the same index. + * + * The child fwnode reched at the end of the iteration is then returned to the + * caller. + * + * The core reason for this is that you cannot refer to just any node in ACPI. + * So to refer to an endpoint (easy in DT) you need to refer to a device, then + * provide a list of (property name, property value) tuples where each tuple + * uniquely identifies a child node. The first tuple identifies a child directly + * underneath the device fwnode, the next tuple identifies a child node + * underneath the fwnode identified by the previous tuple, etc. until you + * reached the fwnode you need. + * + * An example with a graph, as defined in Documentation/acpi/dsd/graph.txt: + * + * Scope (\_SB.PCI0.I2C2) + * { + * Device (CAM0) + * { + * Name (_DSD, Package () { + * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + * Package () { + * Package () { + * "compatible", + * Package () { "nokia,smia" } + * }, + * }, + * ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"), + * Package () { + * Package () { "port0", "PRT0" }, + * } + * }) + * Name (PRT0, Package() { + * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + * Package () { + * Package () { "port", 0 }, + * }, + * ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"), + * Package () { + * Package () { "endpoint0", "EP00" }, + * } + * }) + * Name (EP00, Package() { + * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + * Package () { + * Package () { "endpoint", 0 }, + * Package () { + * "remote-endpoint", + * Package() { + * \_SB.PCI0.ISP, 4, 0 + * } + * }, + * } + * }) + * } + * } + * + * Scope (\_SB.PCI0) + * { + * Device (ISP) + * { + * Name (_DSD, Package () { + * ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"), + * Package () { + * Package () { "port4", "PRT4" }, + * } + * }) + * + * Name (PRT4, Package() { + * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + * Package () { + * Package () { "port", 4 }, + * }, + * ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"), + * Package () { + * Package () { "endpoint0", "EP40" }, + * } + * }) + * + * Name (EP40, Package() { + * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + * Package () { + * Package () { "endpoint", 0 }, + * Package () { + * "remote-endpoint", + * Package () { + * \_SB.PCI0.I2C2.CAM0, + * 0, 0 + * } + * }, + * } + * }) + * } + * } + * + * From the EP40 node under ISP device, you could parse the graph remote + * endpoint using v4l2_fwnode_reference_get_int_prop with these arguments: + * + * @fwnode: fwnode referring to EP40 under ISP. + * @prop: "remote-endpoint" + * @index: 0 + * @props: "port", "endpoint" + * @nprops: 2 + * + * And you'd get back fwnode referring to EP00 under CAM0. + * + * The same works the other way around: if you use EP00 under CAM0 as the + * fwnode, you'll get fwnode referring to EP40 under ISP. + * + * The same example in DT syntax would look like this: + * + * cam: cam0 { + * compatible = "nokia,smia"; + * + * port { + * port = <0>; + * endpoint { + * endpoint = <0>; + * remote-endpoint = <&isp 4 0>; + * }; + * }; + * }; + * + * isp: isp { + * ports { + * port@4 { + * port = <4>; + * endpoint { + * endpoint = <0>; + * remote-endpoint = <&cam 0 0>; + * }; + * }; + * }; + * }; + * + * Return: 0 on success + * -ENOENT if no entries (or the property itself) were found + * -EINVAL if property parsing otherwise failed + * -ENOMEM if memory allocation failed + */ +static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop( + struct fwnode_handle *fwnode, const char *prop, unsigned int index, + const char * const *props, unsigned int nprops) +{ + struct fwnode_reference_args fwnode_args; + unsigned int *args = fwnode_args.args; + struct fwnode_handle *child; + int ret; + + /* + * Obtain remote fwnode as well as the integer arguments. + * + * Note that right now both -ENODATA and -ENOENT may signal + * out-of-bounds access. Return -ENOENT in that case. + */ + ret = fwnode_property_get_reference_args(fwnode, prop, NULL, nprops, + index, &fwnode_args); + if (ret) + return ERR_PTR(ret == -ENODATA ? -ENOENT : ret); + + /* + * Find a node in the tree under the referred fwnode corresponding to + * the integer arguments. + */ + fwnode = fwnode_args.fwnode; + while (nprops--) { + u32 val; + + /* Loop over all child nodes under fwnode. */ + fwnode_for_each_child_node(fwnode, child) { + if (fwnode_property_read_u32(child, *props, &val)) + continue; + + /* Found property, see if its value matches. */ + if (val == *args) + break; + } + + fwnode_handle_put(fwnode); + + /* No property found; return an error here. */ + if (!child) { + fwnode = ERR_PTR(-ENOENT); + break; + } + + props++; + args++; + fwnode = child; + } + + return fwnode; +} + +/* + * v4l2_fwnode_reference_parse_int_props - parse references for async + * sub-devices + * @dev: struct device pointer + * @notifier: notifier for @dev + * @prop: the name of the property + * @props: the array of integer property names + * @nprops: the number of integer properties + * + * Use v4l2_fwnode_reference_get_int_prop to find fwnodes through reference in + * property @prop with integer arguments with child nodes matching in properties + * @props. Then, set up V4L2 async sub-devices for those fwnodes in the notifier + * accordingly. + * + * While it is technically possible to use this function on DT, it is only + * meaningful on ACPI. On Device tree you can refer to any node in the tree but + * on ACPI the references are limited to devices. + * + * Return: 0 on success + * -ENOENT if no entries (or the property itself) were found + * -EINVAL if property parsing otherwisefailed + * -ENOMEM if memory allocation failed + */ +static int v4l2_fwnode_reference_parse_int_props( + struct device *dev, struct v4l2_async_notifier *notifier, + const char *prop, const char * const *props, unsigned int nprops) +{ + struct fwnode_handle *fwnode; + unsigned int index; + int ret; + + for (index = 0; !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop( + dev_fwnode(dev), prop, index, props, + nprops))); index++) + fwnode_handle_put(fwnode); + + /* + * Note that right now both -ENODATA and -ENOENT may signal + * out-of-bounds access. Return the error in cases other than that. + */ + if (PTR_ERR(fwnode) != -ENOENT && PTR_ERR(fwnode) != -ENODATA) + return PTR_ERR(fwnode); + + ret = v4l2_async_notifier_realloc(notifier, + notifier->num_subdevs + index); + if (ret) + return -ENOMEM; + + for (index = 0; !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop( + dev_fwnode(dev), prop, index, props, + nprops))); index++) { + struct v4l2_async_subdev *asd; + + if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) { + ret = -EINVAL; + goto error; + } + + asd = kzalloc(sizeof(struct v4l2_async_subdev), GFP_KERNEL); + if (!asd) { + ret = -ENOMEM; + goto error; + } + + notifier->subdevs[notifier->num_subdevs] = asd; + asd->match.fwnode.fwnode = fwnode; + asd->match_type = V4L2_ASYNC_MATCH_FWNODE; + notifier->num_subdevs++; + } + + return PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode); + +error: + fwnode_handle_put(fwnode); + return ret; +} + +int v4l2_async_notifier_parse_fwnode_sensor_common( + struct device *dev, struct v4l2_async_notifier *notifier) +{ + static const char * const led_props[] = { "led" }; + static const struct { + const char *name; + const char * const *props; + unsigned int nprops; + } props[] = { + { "flash-leds", led_props, ARRAY_SIZE(led_props) }, + { "lens-focus", NULL, 0 }, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(props); i++) { + int ret; + + if (props[i].props && is_acpi_node(dev_fwnode(dev))) + ret = v4l2_fwnode_reference_parse_int_props( + dev, notifier, props[i].name, + props[i].props, props[i].nprops); + else + ret = v4l2_fwnode_reference_parse( + dev, notifier, props[i].name); + if (ret && ret != -ENOENT) { + dev_warn(dev, "parsing property \"%s\" failed (%d)\n", + props[i].name, ret); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_sensor_common); + +int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd) +{ + struct v4l2_async_notifier *notifier; + int ret; + + if (WARN_ON(!sd->dev)) + return -ENODEV; + + notifier = kzalloc(sizeof(*notifier), GFP_KERNEL); + if (!notifier) + return -ENOMEM; + + ret = v4l2_async_notifier_parse_fwnode_sensor_common(sd->dev, + notifier); + if (ret < 0) + goto out_cleanup; + + ret = v4l2_async_subdev_notifier_register(sd, notifier); + if (ret < 0) + goto out_cleanup; + + ret = v4l2_async_register_subdev(sd); + if (ret < 0) + goto out_unregister; + + sd->subdev_notifier = notifier; + + return 0; + +out_unregister: + v4l2_async_notifier_unregister(notifier); + +out_cleanup: + v4l2_async_notifier_cleanup(notifier); + kfree(notifier); + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>"); MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index b60a6b0841d1..79614992ee21 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -730,9 +730,12 @@ static void v4l_print_frmsizeenum(const void *arg, bool write_only) break; case V4L2_FRMSIZE_TYPE_STEPWISE: pr_cont(", min=%ux%u, max=%ux%u, step=%ux%u\n", - p->stepwise.min_width, p->stepwise.min_height, - p->stepwise.step_width, p->stepwise.step_height, - p->stepwise.max_width, p->stepwise.max_height); + p->stepwise.min_width, + p->stepwise.min_height, + p->stepwise.max_width, + p->stepwise.max_height, + p->stepwise.step_width, + p->stepwise.step_height); break; case V4L2_FRMSIZE_TYPE_CONTINUOUS: /* fall through */ diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index f62e68aa04c4..bc580fbe18fa 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -183,6 +183,7 @@ EXPORT_SYMBOL(v4l2_m2m_get_curr_priv); /** * v4l2_m2m_try_run() - select next job to perform and run it if possible + * @m2m_dev: per-device context * * Get next transaction (if present) from the waiting jobs list and run it. */ @@ -281,6 +282,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_try_schedule); /** * v4l2_m2m_cancel_job() - cancel pending jobs for the context + * @m2m_ctx: m2m context with jobs to be canceled * * In case of streamoff or release called on any context, * 1] If the context is currently running, then abort job will be called diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c index 1dbf6f7785bb..e87fb13b22dc 100644 --- a/drivers/media/v4l2-core/videobuf-core.c +++ b/drivers/media/v4l2-core/videobuf-core.c @@ -222,7 +222,7 @@ int videobuf_queue_is_busy(struct videobuf_queue *q) } EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); -/** +/* * __videobuf_free() - free all the buffers and their control structures * * This function can only be called if streaming/reading is off, i.e. no buffers diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c index 0b5c43f7e020..f412429cf5ba 100644 --- a/drivers/media/v4l2-core/videobuf-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf-dma-sg.c @@ -185,12 +185,13 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n", data, size, dma->nr_pages); - err = get_user_pages(data & PAGE_MASK, dma->nr_pages, + err = get_user_pages_longterm(data & PAGE_MASK, dma->nr_pages, flags, dma->pages, NULL); if (err != dma->nr_pages) { dma->nr_pages = (err >= 0) ? err : 0; - dprintk(1, "get_user_pages: err=%d [%d]\n", err, dma->nr_pages); + dprintk(1, "get_user_pages_longterm: err=%d [%d]\n", err, + dma->nr_pages); return err < 0 ? err : -EINVAL; } return 0; diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index cb115ba6a1d2..a8589d96ef72 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -188,7 +188,7 @@ module_param(debug, int, 0644); static void __vb2_queue_cancel(struct vb2_queue *q); static void __enqueue_in_driver(struct vb2_buffer *vb); -/** +/* * __vb2_buf_mem_alloc() - allocate video memory for the given buffer */ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) @@ -229,7 +229,7 @@ free: return ret; } -/** +/* * __vb2_buf_mem_free() - free memory of the given buffer */ static void __vb2_buf_mem_free(struct vb2_buffer *vb) @@ -243,7 +243,7 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb) } } -/** +/* * __vb2_buf_userptr_put() - release userspace memory associated with * a USERPTR buffer */ @@ -258,7 +258,7 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb) } } -/** +/* * __vb2_plane_dmabuf_put() - release memory associated with * a DMABUF shared plane */ @@ -277,7 +277,7 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p) p->dbuf_mapped = 0; } -/** +/* * __vb2_buf_dmabuf_put() - release memory associated with * a DMABUF shared buffer */ @@ -289,7 +289,7 @@ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb) __vb2_plane_dmabuf_put(vb, &vb->planes[plane]); } -/** +/* * __setup_offsets() - setup unique offsets ("cookies") for every plane in * the buffer. */ @@ -317,7 +317,7 @@ static void __setup_offsets(struct vb2_buffer *vb) } } -/** +/* * __vb2_queue_alloc() - allocate videobuf buffer structures and (for MMAP type) * video buffer memory for all buffers/planes on the queue and initializes the * queue @@ -386,7 +386,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory, return buffer; } -/** +/* * __vb2_free_mem() - release all video buffer memory for a given queue */ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers) @@ -410,7 +410,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers) } } -/** +/* * __vb2_queue_free() - free buffers at the end of the queue - video memory and * related information, if no buffers are left return the queue to an * uninitialized state. Might be called even if the queue has already been freed. @@ -544,7 +544,7 @@ bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb) } EXPORT_SYMBOL(vb2_buffer_in_use); -/** +/* * __buffers_in_use() - return true if any buffers on the queue are in use and * the queue cannot be freed (by the means of REQBUFS(0)) call */ @@ -564,7 +564,7 @@ void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb) } EXPORT_SYMBOL_GPL(vb2_core_querybuf); -/** +/* * __verify_userptr_ops() - verify that all memory operations required for * USERPTR queue type have been provided */ @@ -577,7 +577,7 @@ static int __verify_userptr_ops(struct vb2_queue *q) return 0; } -/** +/* * __verify_mmap_ops() - verify that all memory operations required for * MMAP queue type have been provided */ @@ -590,7 +590,7 @@ static int __verify_mmap_ops(struct vb2_queue *q) return 0; } -/** +/* * __verify_dmabuf_ops() - verify that all memory operations required for * DMABUF queue type have been provided */ @@ -953,7 +953,7 @@ void vb2_discard_done(struct vb2_queue *q) } EXPORT_SYMBOL_GPL(vb2_discard_done); -/** +/* * __prepare_mmap() - prepare an MMAP buffer */ static int __prepare_mmap(struct vb2_buffer *vb, const void *pb) @@ -966,7 +966,7 @@ static int __prepare_mmap(struct vb2_buffer *vb, const void *pb) return ret ? ret : call_vb_qop(vb, buf_prepare, vb); } -/** +/* * __prepare_userptr() - prepare a USERPTR buffer */ static int __prepare_userptr(struct vb2_buffer *vb, const void *pb) @@ -1082,7 +1082,7 @@ err: return ret; } -/** +/* * __prepare_dmabuf() - prepare a DMABUF buffer */ static int __prepare_dmabuf(struct vb2_buffer *vb, const void *pb) @@ -1215,7 +1215,7 @@ err: return ret; } -/** +/* * __enqueue_in_driver() - enqueue a vb2_buffer in driver for processing */ static void __enqueue_in_driver(struct vb2_buffer *vb) @@ -1298,7 +1298,7 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb) } EXPORT_SYMBOL_GPL(vb2_core_prepare_buf); -/** +/* * vb2_start_streaming() - Attempt to start streaming. * @q: videobuf2 queue * @@ -1427,7 +1427,7 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) } EXPORT_SYMBOL_GPL(vb2_core_qbuf); -/** +/* * __vb2_wait_for_done_vb() - wait for a buffer to become available * for dequeuing * @@ -1502,7 +1502,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) return 0; } -/** +/* * __vb2_get_done_vb() - get a buffer ready for dequeuing * * Will sleep if required for nonblocking == false. @@ -1553,7 +1553,7 @@ int vb2_wait_for_all_buffers(struct vb2_queue *q) } EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers); -/** +/* * __vb2_dqbuf() - bring back the buffer to the DEQUEUED state */ static void __vb2_dqbuf(struct vb2_buffer *vb) @@ -1625,7 +1625,7 @@ int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb, } EXPORT_SYMBOL_GPL(vb2_core_dqbuf); -/** +/* * __vb2_queue_cancel() - cancel and stop (pause) streaming * * Removes all queued buffers from driver's queue and all buffers queued by @@ -1773,7 +1773,7 @@ int vb2_core_streamoff(struct vb2_queue *q, unsigned int type) } EXPORT_SYMBOL_GPL(vb2_core_streamoff); -/** +/* * __find_plane_by_offset() - find plane associated with the given offset off */ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off, @@ -2104,7 +2104,7 @@ unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file, } EXPORT_SYMBOL_GPL(vb2_core_poll); -/** +/* * struct vb2_fileio_buf - buffer context used by file io emulator * * vb2 provides a compatibility layer and emulator of file io (read and @@ -2118,7 +2118,7 @@ struct vb2_fileio_buf { unsigned int queued:1; }; -/** +/* * struct vb2_fileio_data - queue context used by file io emulator * * @cur_index: the index of the buffer currently being read from or @@ -2155,7 +2155,7 @@ struct vb2_fileio_data { unsigned write_immediately:1; }; -/** +/* * __vb2_init_fileio() - initialize file io emulator * @q: videobuf2 queue * @read: mode selector (1 means read, 0 means write) @@ -2274,7 +2274,7 @@ err_kfree: return ret; } -/** +/* * __vb2_cleanup_fileio() - free resourced used by file io emulator * @q: videobuf2 queue */ @@ -2293,7 +2293,7 @@ static int __vb2_cleanup_fileio(struct vb2_queue *q) return 0; } -/** +/* * __vb2_perform_fileio() - perform a single file io (read or write) operation * @q: videobuf2 queue * @data: pointed to target userspace buffer diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index 9f389f36566d..a9806ba6116d 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -479,7 +479,7 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, { struct vb2_dc_buf *buf; struct frame_vector *vec; - unsigned long offset; + unsigned int offset; int n_pages, i; int ret = 0; struct sg_table *sgt; @@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, buf->dev = dev; buf->dma_dir = dma_dir; - offset = vaddr & ~PAGE_MASK; + offset = lower_32_bits(offset_in_page(vaddr)); vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE || dma_dir == DMA_BIDIRECTIONAL); if (IS_ERR(vec)) { diff --git a/drivers/media/v4l2-core/videobuf2-memops.c b/drivers/media/v4l2-core/videobuf2-memops.c index 4bb8424114ce..89e51989332b 100644 --- a/drivers/media/v4l2-core/videobuf2-memops.c +++ b/drivers/media/v4l2-core/videobuf2-memops.c @@ -120,7 +120,7 @@ static void vb2_common_vm_close(struct vm_area_struct *vma) h->put(h->arg); } -/** +/* * vb2_common_vm_ops - common vm_ops used for tracking refcount of mmaped * video buffers */ diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index 0c0669976bdc..4075314a6989 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -49,7 +49,7 @@ module_param(debug, int, 0644); #define V4L2_BUFFER_OUT_FLAGS (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \ V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE) -/** +/* * __verify_planes_array() - verify that the planes array passed in struct * v4l2_buffer from userspace can be safely used */ @@ -78,7 +78,7 @@ static int __verify_planes_array_core(struct vb2_buffer *vb, const void *pb) return __verify_planes_array(vb, pb); } -/** +/* * __verify_length() - Verify that the bytesused value for each plane fits in * the plane length and that the data offset doesn't exceed the bytesused value. */ @@ -181,7 +181,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, return __verify_planes_array(q->bufs[b->index], b); } -/** +/* * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be * returned to userspace */ @@ -286,7 +286,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) q->last_buffer_dequeued = true; } -/** +/* * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a * v4l2_buffer by the userspace. It also verifies that struct * v4l2_buffer has a valid number of planes. @@ -446,7 +446,7 @@ static const struct vb2_buf_ops v4l2_buf_ops = { .copy_timestamp = __copy_timestamp, }; -/** +/* * vb2_querybuf() - query video buffer information * @q: videobuf queue * @b: buffer struct passed from userspace to vidioc_querybuf handler |