diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-11 22:17:44 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-11 22:17:44 -0800 |
commit | 47c62e4be78303ef52ffa8134026919d0890c5a9 (patch) | |
tree | c0ece2346076651da1f9fb33261d89f43b711be9 /drivers/media | |
parent | 2c487121e3c4f87e82cff493872675bde52e47fc (diff) | |
parent | c3152592e70bbf023ec106ee9ea271e9060bc09a (diff) |
Merge tag 'media/v4.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
"The part of patches for Kernel 4.5. There's nothing really big here:
- driver-specific headers for media devices were moved to separate
directories, in order to make clear what headers belong to the core
kABI and require documentation
- Platform data for media drivers were moved from include/media to
include/linux/platform_data/media
- add a driver for cs3308 8-channel volume control, used on some
high-end capture boards
- lirc.h kAPI header were added at include/uapi/linux
- Driver cleanups, new board additions and improvements"
* tag 'media/v4.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (204 commits)
[media] rc: sunxi-cir: Initialize the spinlock properly
[media] rtl2832: do not filter out slave TS null packets
[media] rtl2832: print reg number on error case
[media] rtl28xxu: return demod reg page from driver cache
[media] coda: enable MPEG-2 ES decoding
[media] coda: don't start streaming without queued buffers
[media] coda: hook up vidioc_prepare_buf
[media] coda: relax coda_jpeg_check_buffer for trailing bytes
[media] coda: make to_coda_video_device static
[media] s5p-mfc: remove volatile attribute from MFC register addresses
[media] s5p-mfc: merge together s5p_mfc_hw_call and s5p_mfc_hw_call_void
[media] s5p-mfc: use spinlock to protect MFC context
[media] s5p-mfc: remove unnecessary callbacks
[media] s5p-mfc: make queue cleanup code common
[media] s5p-mfc: use one implementation of s5p_mfc_get_new_ctx
[media] s5p-mfc: constify s5p_mfc_codec_ops structures
[media] au8522: Avoid memory leak for device config data
[media] ir-lirc-codec.c: don't leak lirc->drv-rbuf
[media] uvcvideo: small cleanup in uvc_video_clock_update()
[media] uvcvideo: Fix reading the current exposure value of UVC
...
Diffstat (limited to 'drivers/media')
357 files changed, 3783 insertions, 3389 deletions
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 3ef3d6c6bbf8..9264ea73b3be 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -9,7 +9,7 @@ menuconfig MEDIA_SUPPORT If you want to use Webcams, Video grabber devices and/or TV devices enable this option and other options below. Additional info and docs are available on the web at - <http://linuxtv.org> + <https://linuxtv.org> if MEDIA_SUPPORT @@ -51,7 +51,7 @@ config MEDIA_RADIO_SUPPORT Enable AM/FM radio support. Additional info and docs are available on the web at - <http://linuxtv.org> + <https://linuxtv.org> Say Y when you have a board with radio support. diff --git a/drivers/media/common/cx2341x.c b/drivers/media/common/cx2341x.c index c07b9db51b05..5e4afa0131e6 100644 --- a/drivers/media/common/cx2341x.c +++ b/drivers/media/common/cx2341x.c @@ -27,7 +27,7 @@ #include <linux/videodev2.h> #include <media/tuner.h> -#include <media/cx2341x.h> +#include <media/drv-intf/cx2341x.h> #include <media/v4l2-common.h> MODULE_DESCRIPTION("cx23415/6/8 driver"); diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c index 1ff9f5323bc3..9f7c5b0a6b45 100644 --- a/drivers/media/common/saa7146/saa7146_core.c +++ b/drivers/media/common/saa7146/saa7146_core.c @@ -20,7 +20,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <media/saa7146.h> +#include <media/drv-intf/saa7146.h> #include <linux/module.h> static int saa7146_num; diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c index df1e8c975cd8..930d2c94d5d3 100644 --- a/drivers/media/common/saa7146/saa7146_fops.c +++ b/drivers/media/common/saa7146/saa7146_fops.c @@ -1,6 +1,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <media/saa7146_vv.h> +#include <media/drv-intf/saa7146_vv.h> #include <linux/module.h> /****************************************************************************/ diff --git a/drivers/media/common/saa7146/saa7146_hlp.c b/drivers/media/common/saa7146/saa7146_hlp.c index 3dc6a838ca6f..6ebcbc6450f5 100644 --- a/drivers/media/common/saa7146/saa7146_hlp.c +++ b/drivers/media/common/saa7146/saa7146_hlp.c @@ -2,7 +2,7 @@ #include <linux/kernel.h> #include <linux/export.h> -#include <media/saa7146_vv.h> +#include <media/drv-intf/saa7146_vv.h> static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format) { diff --git a/drivers/media/common/saa7146/saa7146_i2c.c b/drivers/media/common/saa7146/saa7146_i2c.c index 22027198129d..239a2db35068 100644 --- a/drivers/media/common/saa7146/saa7146_i2c.c +++ b/drivers/media/common/saa7146/saa7146_i2c.c @@ -1,6 +1,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <media/saa7146_vv.h> +#include <media/drv-intf/saa7146_vv.h> static u32 saa7146_i2c_func(struct i2c_adapter *adapter) { diff --git a/drivers/media/common/saa7146/saa7146_vbi.c b/drivers/media/common/saa7146/saa7146_vbi.c index 2da995758778..49237518d65f 100644 --- a/drivers/media/common/saa7146/saa7146_vbi.c +++ b/drivers/media/common/saa7146/saa7146_vbi.c @@ -1,4 +1,4 @@ -#include <media/saa7146_vv.h> +#include <media/drv-intf/saa7146_vv.h> static int vbi_pixel_to_capture = 720 * 2; diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c index 30779498c173..d5837be3e8cf 100644 --- a/drivers/media/common/saa7146/saa7146_video.c +++ b/drivers/media/common/saa7146/saa7146_video.c @@ -1,6 +1,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <media/saa7146_vv.h> +#include <media/drv-intf/saa7146_vv.h> #include <media/v4l2-event.h> #include <media/v4l2-ctrls.h> #include <linux/module.h> diff --git a/drivers/media/common/siano/smsir.h b/drivers/media/common/siano/smsir.h index fc8b7925c532..d9abd96ef48b 100644 --- a/drivers/media/common/siano/smsir.h +++ b/drivers/media/common/siano/smsir.h @@ -30,8 +30,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include <linux/input.h> #include <media/rc-core.h> -#define IR_DEFAULT_TIMEOUT 100 - struct smscore_device_t; struct ir_t { diff --git a/drivers/media/dvb-core/demux.h b/drivers/media/dvb-core/demux.h index ccc1f43cb9a9..6d3b95b8939d 100644 --- a/drivers/media/dvb-core/demux.h +++ b/drivers/media/dvb-core/demux.h @@ -32,6 +32,49 @@ #include <linux/time.h> #include <linux/dvb/dmx.h> +/** + * DOC: Digital TV Demux + * + * The Kernel Digital TV Demux kABI defines a driver-internal interface for + * registering low-level, hardware specific driver to a hardware independent + * demux layer. It is only of interest for Digital TV device driver writers. + * The header file for this kABI is named demux.h and located in + * drivers/media/dvb-core. + * + * The demux kABI should be implemented for each demux in the system. It is + * used to select the TS source of a demux and to manage the demux resources. + * When the demux client allocates a resource via the demux kABI, it receives + * a pointer to the kABI of that resource. + * + * Each demux receives its TS input from a DVB front-end or from memory, as + * set via this demux kABI. In a system with more than one front-end, the kABI + * can be used to select one of the DVB front-ends as a TS source for a demux, + * unless this is fixed in the HW platform. + * + * The demux kABI only controls front-ends regarding to their connections with + * demuxes; the kABI used to set the other front-end parameters, such as + * tuning, are devined via the Digital TV Frontend kABI. + * + * The functions that implement the abstract interface demux should be defined + * static or module private and registered to the Demux core for external + * access. It is not necessary to implement every function in the struct + * &dmx_demux. For example, a demux interface might support Section filtering, + * but not PES filtering. The kABI client is expected to check the value of any + * function pointer before calling the function: the value of NULL means + * that the function is not available. + * + * Whenever the functions of the demux API modify shared data, the + * possibilities of lost update and race condition problems should be + * addressed, e.g. by protecting parts of code with mutexes. + * + * Note that functions called from a bottom half context must not sleep. + * Even a simple memory allocation without using %GFP_ATOMIC can result in a + * kernel thread being put to sleep if swapping is needed. For example, the + * Linux Kernel calls the functions of a network device interface from a + * bottom half context. Thus, if a demux kABI function is called from network + * device code, the function must not sleep. + */ + /* * Common definitions */ @@ -187,8 +230,28 @@ struct dmx_section_feed { int (*stop_filtering)(struct dmx_section_feed *feed); }; -/* - * Callback functions +/** + * DOC: Demux Callback + * + * This kernel-space API comprises the callback functions that deliver filtered + * data to the demux client. Unlike the other DVB kABIs, these functions are + * provided by the client and called from the demux code. + * + * The function pointers of this abstract interface are not packed into a + * structure as in the other demux APIs, because the callback functions are + * registered and used independent of each other. As an example, it is possible + * for the API client to provide several callback functions for receiving TS + * packets and no callbacks for PES packets or sections. + * + * The functions that implement the callback API need not be re-entrant: when + * a demux driver calls one of these functions, the driver is not allowed to + * call the function again before the original call returns. If a callback is + * triggered by a hardware interrupt, it is recommended to use the Linux + * bottom half mechanism or start a tasklet instead of making the callback + * function call directly from a hardware interrupt. + * + * This mechanism is implemented by dmx_ts_cb() and dmx_section_cb() + * callbacks. */ /** diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 0a46580b5376..1c1c298d2289 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -389,4 +389,5 @@ #define USB_PID_PCTV_2002E_SE 0x025d #define USB_PID_SVEON_STV27 0xd3af #define USB_PID_TURBOX_DTT_2000 0xd3a4 +#define USB_PID_WINTV_SOLOHD 0x0264 #endif diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index c38ef1a72b4a..b64f33776b74 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -891,21 +891,21 @@ static void dvb_frontend_stop(struct dvb_frontend *fe) } /* - * Sleep until gettimeofday() > waketime + add_usec - * This needs to be as precise as possible, but as the delay is - * usually between 2ms and 32ms, it is done using a scheduled msleep - * followed by usleep (normally a busy-wait loop) for the remainder + * Sleep for the amount of time given by add_usec parameter + * + * This needs to be as precise as possible, as it affects the detection of + * the dish tone command at the satellite subsystem. The precision is improved + * by using a scheduled msleep followed by udelay for the remainder. */ void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec) { - s32 delta, newdelta; + s32 delta; - ktime_add_us(*waketime, add_usec); + *waketime = ktime_add_us(*waketime, add_usec); delta = ktime_us_delta(ktime_get_real(), *waketime); if (delta > 2500) { msleep((delta - 1500) / 1000); - newdelta = ktime_us_delta(ktime_get_real(), *waketime); - delta = (newdelta > delta) ? 0 : newdelta; + delta = ktime_us_delta(ktime_get_real(), *waketime); } if (delta > 0) udelay(delta); @@ -2313,9 +2313,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file, dev_dbg(fe->dvb->device, "%s: current delivery system on cache: %d, V3 type: %d\n", __func__, c->delivery_system, fe->ops.info.type); - /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't - * do it, it is done for it. */ - info->caps |= FE_CAN_INVERSION_AUTO; + /* Set CAN_INVERSION_AUTO bit on in other than oneshot mode */ + if (!(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) + info->caps |= FE_CAN_INVERSION_AUTO; err = 0; break; } @@ -2710,6 +2710,11 @@ int dvb_frontend_resume(struct dvb_frontend *fe) else if (fe->ops.tuner_ops.init) ret = fe->ops.tuner_ops.init(fe); + if (fe->ops.set_tone && fepriv->tone != -1) + fe->ops.set_tone(fe, fepriv->tone); + if (fe->ops.set_voltage && fepriv->voltage != -1) + fe->ops.set_voltage(fe, fepriv->voltage); + fe->exit = DVB_FE_NO_EXIT; fepriv->state = FESTATE_RETUNE; dvb_frontend_wakeup(fe); diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h index 97661b2f247a..458bcce20e38 100644 --- a/drivers/media/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb-core/dvb_frontend.h @@ -42,6 +42,29 @@ #include "dvbdev.h" +/** + * DOC: Digital TV Frontend + * + * The Digital TV Frontend kABI defines a driver-internal interface for + * registering low-level, hardware specific driver to a hardware independent + * frontend layer. It is only of interest for Digital TV device driver writers. + * The header file for this API is named dvb_frontend.h and located in + * drivers/media/dvb-core. + * + * Before using the Digital TV frontend core, the bridge driver should attach + * the frontend demod, tuner and SEC devices and call dvb_register_frontend(), + * in order to register the new frontend at the subsystem. At device + * detach/removal, the bridge driver should call dvb_unregister_frontend() to + * remove the frontend from the core and then dvb_frontend_detach() to free the + * memory allocated by the frontend drivers. + * + * The drivers should also call dvb_frontend_suspend() as part of their + * handler for the &device_driver.suspend(), and dvb_frontend_resume() as + * part of their handler for &device_driver.resume(). + * + * A few other optional functions are provided to handle some special cases. + */ + /* * Maximum number of Delivery systems per frontend. It * should be smaller or equal to 32 @@ -112,16 +135,6 @@ struct analog_parameters { u64 std; }; -enum tuner_param { - DVBFE_TUNER_FREQUENCY = (1 << 0), - DVBFE_TUNER_TUNERSTEP = (1 << 1), - DVBFE_TUNER_IFFREQ = (1 << 2), - DVBFE_TUNER_BANDWIDTH = (1 << 3), - DVBFE_TUNER_REFCLOCK = (1 << 4), - DVBFE_TUNER_IQSENSE = (1 << 5), - DVBFE_TUNER_DUMMY = (1 << 31) -}; - /** * enum dvbfe_algo - defines the algorithm used to tune into a channel * @@ -152,15 +165,6 @@ enum dvbfe_algo { DVBFE_ALGO_RECOVERY = (1 << 31) }; -struct tuner_state { - u32 frequency; - u32 tunerstep; - u32 ifreq; - u32 bandwidth; - u32 iqsense; - u32 refclock; -}; - /** * enum dvbfe_search - search callback possible return status * @@ -209,12 +213,12 @@ enum dvbfe_search { * 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 - * update statistics. + * 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; * to the driver. - * @calc_regs: callback function used to pass register data settings - * for simple tuners. * @set_config: callback function used to send some tuner-specific * parameters. * @get_frequency: get the actual tuned frequency @@ -227,16 +231,10 @@ enum dvbfe_search { * via DVBv5 API (@dvb_frontend.dtv_property_cache;). * @get_afc: Used only by analog TV core. Reports the frequency * drift due to AFC. - * @set_frequency: Set a new frequency. Please notice that using - * set_params is preferred. - * @set_bandwidth: Set a new frequency. Please notice that using - * set_params is preferred. - * @set_state: callback function used on some legacy drivers that - * don't implement set_params in order to set properties. - * Shouldn't be used on new drivers. - * @get_state: callback function used to get properties by some - * legacy drivers that don't implement set_params. - * Shouldn't be used on new drivers. + * @calc_regs: callback function used to pass register data settings + * for simple tuners. Shouldn't be used on newer drivers. + * @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 * terrestrial/cable or kHz for satellite. @@ -252,14 +250,10 @@ struct dvb_tuner_ops { int (*suspend)(struct dvb_frontend *fe); int (*resume)(struct dvb_frontend *fe); - /** This is for simple PLLs - set all parameters in one go. */ + /* This is the recomended way to set the tuner */ int (*set_params)(struct dvb_frontend *fe); int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p); - /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */ - int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len); - - /** This is to allow setting tuner-specific configs */ int (*set_config)(struct dvb_frontend *fe, void *priv_cfg); int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency); @@ -272,17 +266,23 @@ struct dvb_tuner_ops { int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength); int (*get_afc)(struct dvb_frontend *fe, s32 *afc); - /** These are provided separately from set_params in order to facilitate silicon - * tuners which require sophisticated tuning loops, controlling each parameter separately. */ - int (*set_frequency)(struct dvb_frontend *fe, u32 frequency); - int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth); + /* + * This is support for demods like the mt352 - fills out the supplied + * buffer with what to write. + * + * Don't use on newer drivers. + */ + int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len); /* - * These are provided separately from set_params in order to facilitate silicon - * tuners which require sophisticated tuning loops, controlling each parameter separately. + * These are provided separately from set_params in order to + * facilitate silicon tuners which require sophisticated tuning loops, + * controlling each parameter separately. + * + * Don't use on newer drivers. */ - int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state); - int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state); + int (*set_frequency)(struct dvb_frontend *fe, u32 frequency); + int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth); }; /** @@ -404,6 +404,11 @@ struct dtv_frontend_properties; * 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). + * 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 + * when backward compatibility with this legacy API is + * required. * @i2c_gate_ctrl: controls the I2C gate. Newer drivers should use I2C * mux support instead. * @ts_bus_ctrl: callback function used to take control of the TS bus. @@ -466,7 +471,8 @@ struct dvb_frontend_ops { int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire); int (*set_lna)(struct dvb_frontend *); - /* These callbacks are for devices that implement their own + /* + * These callbacks are for devices that implement their own * tuning algorithms, rather than a simple swzigzag */ enum dvbfe_search (*search)(struct dvb_frontend *fe); @@ -682,17 +688,126 @@ struct dvb_frontend { unsigned int exit; }; -extern int dvb_register_frontend(struct dvb_adapter *dvb, +/** + * dvb_register_frontend() - Registers a DVB frontend at the adapter + * + * @dvb: pointer to the dvb adapter + * @fe: pointer to the frontend struct + * + * Allocate and initialize the private data needed by the frontend core to + * manage the frontend and calls dvb_register_device() to register a new + * frontend. It also cleans the property cache that stores the frontend + * parameters and selects the first available delivery system. + */ +int dvb_register_frontend(struct dvb_adapter *dvb, struct dvb_frontend *fe); -extern int dvb_unregister_frontend(struct dvb_frontend *fe); +/** + * dvb_unregister_frontend() - Unregisters a DVB frontend + * + * @fe: pointer to the frontend struct + * + * Stops the frontend kthread, calls dvb_unregister_device() and frees the + * private frontend data allocated by dvb_register_frontend(). + * + * NOTE: This function doesn't frees the memory allocated by the demod, + * by the SEC driver and by the tuner. In order to free it, an explicit call to + * dvb_frontend_detach() is needed, after calling this function. + */ +int dvb_unregister_frontend(struct dvb_frontend *fe); -extern void dvb_frontend_detach(struct dvb_frontend *fe); +/** + * dvb_frontend_detach() - Detaches and frees frontend specific data + * + * @fe: pointer to the frontend struct + * + * 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 + * the module reference count, needed to allow userspace to remove the + * previously used DVB frontend modules. + */ +void dvb_frontend_detach(struct dvb_frontend *fe); + +/** + * dvb_frontend_suspend() - Suspends a Digital TV frontend + * + * @fe: pointer to the frontend struct + * + * This function prepares a Digital TV frontend to suspend. + * + * In order to prepare the tuner to suspend, if + * &dvb_frontend_ops.tuner_ops.suspend() is available, it calls it. Otherwise, + * it will call &dvb_frontend_ops.tuner_ops.sleep(), if available. + * + * It will also call &dvb_frontend_ops.sleep() to put the demod to suspend. + * + * The drivers should also call dvb_frontend_suspend() as part of their + * handler for the &device_driver.suspend(). + */ +int dvb_frontend_suspend(struct dvb_frontend *fe); + +/** + * dvb_frontend_resume() - Resumes a Digital TV frontend + * + * @fe: pointer to the frontend struct + * + * This function resumes the usual operation of the tuner after resume. + * + * In order to resume the frontend, it calls the demod &dvb_frontend_ops.init(). + * + * If &dvb_frontend_ops.tuner_ops.resume() is available, It, it calls it. + * Otherwise,t will call &dvb_frontend_ops.tuner_ops.init(), if available. + * + * Once tuner and demods are resumed, it will enforce that the SEC voltage and + * tone are restored to their previous values and wake up the frontend's + * kthread in order to retune the frontend. + * + * The drivers should also call dvb_frontend_resume() as part of their + * handler for the &device_driver.resume(). + */ +int dvb_frontend_resume(struct dvb_frontend *fe); -extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); -extern int dvb_frontend_suspend(struct dvb_frontend *fe); -extern int dvb_frontend_resume(struct dvb_frontend *fe); +/** + * dvb_frontend_reinitialise() - forces a reinitialisation at the frontend + * + * @fe: pointer to the frontend struct + * + * Calls &dvb_frontend_ops.init() and &dvb_frontend_ops.tuner_ops.init(), + * and resets SEC tone and voltage (for Satellite systems). + * + * NOTE: Currently, this function is used only by one driver (budget-av). + * It seems to be due to address some special issue with that specific + * frontend. + */ +void dvb_frontend_reinitialise(struct dvb_frontend *fe); -extern void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec); +/** + * dvb_frontend_sleep_until() - Sleep for the amount of time given by + * add_usec parameter + * + * @waketime: pointer to a 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 + * 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() + * callback. + * + * NOTE: it should not be used at the drivers, as the emulation for the + * legacy callback is provided by the Kernel. The only situation where this + * should be at the drivers is when there are some bugs at the hardware that + * would prevent the core emulation to work. On such cases, the driver would + * be writing a &dvb_frontend_ops.dishnetwork_send_legacy_command() and + * calling this function directly. + */ +void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec); #endif diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index 292c9479bb75..310e4b8beae8 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -264,7 +264,7 @@ config DVB_MB86A16 config DVB_TDA10071 tristate "NXP TDA10071" depends on DVB_CORE && I2C - select REGMAP + select REGMAP_I2C default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. diff --git a/drivers/media/dvb-frontends/au8522_common.c b/drivers/media/dvb-frontends/au8522_common.c index 3559ff230045..f135126bc373 100644 --- a/drivers/media/dvb-frontends/au8522_common.c +++ b/drivers/media/dvb-frontends/au8522_common.c @@ -44,7 +44,7 @@ int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) int ret; u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data }; - struct i2c_msg msg = { .addr = state->config->demod_address, + struct i2c_msg msg = { .addr = state->config.demod_address, .flags = 0, .buf = buf, .len = 3 }; ret = i2c_transfer(state->i2c, &msg, 1); @@ -64,9 +64,9 @@ u8 au8522_readreg(struct au8522_state *state, u16 reg) u8 b1[] = { 0 }; struct i2c_msg msg[] = { - { .addr = state->config->demod_address, .flags = 0, + { .addr = state->config.demod_address, .flags = 0, .buf = b0, .len = 2 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, + { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; ret = i2c_transfer(state->i2c, msg, 2); @@ -140,7 +140,7 @@ EXPORT_SYMBOL(au8522_release_state); static int au8522_led_gpio_enable(struct au8522_state *state, int onoff) { - struct au8522_led_config *led_config = state->config->led_cfg; + struct au8522_led_config *led_config = state->config.led_cfg; u8 val; /* bail out if we can't control an LED */ @@ -170,7 +170,7 @@ static int au8522_led_gpio_enable(struct au8522_state *state, int onoff) */ int au8522_led_ctrl(struct au8522_state *state, int led) { - struct au8522_led_config *led_config = state->config->led_cfg; + struct au8522_led_config *led_config = state->config.led_cfg; int i, ret = 0; /* bail out if we can't control an LED */ diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index 28d7dc2fee34..c8f13d8370e5 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -730,7 +730,6 @@ static int au8522_probe(struct i2c_client *client, struct v4l2_ctrl_handler *hdl; struct v4l2_subdev *sd; int instance; - struct au8522_config *demod_config; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, @@ -754,15 +753,7 @@ static int au8522_probe(struct i2c_client *client, break; } - demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL); - if (demod_config == NULL) { - if (instance == 1) - kfree(state); - return -ENOMEM; - } - demod_config->demod_address = 0x8e >> 1; - - state->config = demod_config; + state->config.demod_address = 0x8e >> 1; state->i2c = client->adapter; sd = &state->sd; @@ -784,8 +775,7 @@ static int au8522_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(demod_config); - kfree(state); + au8522_release_state(state); return err; } diff --git a/drivers/media/dvb-frontends/au8522_dig.c b/drivers/media/dvb-frontends/au8522_dig.c index f956f13fb3dc..6c1e97640f3f 100644 --- a/drivers/media/dvb-frontends/au8522_dig.c +++ b/drivers/media/dvb-frontends/au8522_dig.c @@ -566,7 +566,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, au8522_writereg(state, VSB_mod_tab[i].reg, VSB_mod_tab[i].data); - au8522_set_if(fe, state->config->vsb_if); + au8522_set_if(fe, state->config.vsb_if); break; case QAM_64: dprintk("%s() QAM 64\n", __func__); @@ -574,7 +574,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, au8522_writereg(state, QAM64_mod_tab[i].reg, QAM64_mod_tab[i].data); - au8522_set_if(fe, state->config->qam_if); + au8522_set_if(fe, state->config.qam_if); break; case QAM_256: if (zv_mode) { @@ -583,7 +583,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, au8522_writereg(state, QAM256_mod_tab_zv_mode[i].reg, QAM256_mod_tab_zv_mode[i].data); - au8522_set_if(fe, state->config->qam_if); + au8522_set_if(fe, state->config.qam_if); msleep(100); au8522_writereg(state, 0x821a, 0x00); } else { @@ -592,7 +592,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, au8522_writereg(state, QAM256_mod_tab[i].reg, QAM256_mod_tab[i].data); - au8522_set_if(fe, state->config->qam_if); + au8522_set_if(fe, state->config.qam_if); } break; default: @@ -666,7 +666,7 @@ static int au8522_read_status(struct dvb_frontend *fe, enum fe_status *status) *status |= FE_HAS_LOCK | FE_HAS_SYNC; } - switch (state->config->status_mode) { + switch (state->config.status_mode) { case AU8522_DEMODLOCKING: dprintk("%s() DEMODLOCKING\n", __func__); if (*status & FE_HAS_VITERBI) @@ -704,7 +704,7 @@ static int au8522_read_status(struct dvb_frontend *fe, enum fe_status *status) static int au8522_led_status(struct au8522_state *state, const u16 *snr) { - struct au8522_led_config *led_config = state->config->led_cfg; + struct au8522_led_config *led_config = state->config.led_cfg; int led; u16 strong; @@ -758,7 +758,7 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) au8522_readreg(state, 0x4311), snr); - if (state->config->led_cfg) + if (state->config.led_cfg) au8522_led_status(state, snr); return ret; @@ -866,7 +866,7 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config, } /* setup the state */ - state->config = config; + state->config = *config; state->i2c = i2c; state->operational_mode = AU8522_DIGITAL_MODE; diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h index 951b3847e6f6..ee330c61aa61 100644 --- a/drivers/media/dvb-frontends/au8522_priv.h +++ b/drivers/media/dvb-frontends/au8522_priv.h @@ -50,7 +50,7 @@ struct au8522_state { struct list_head hybrid_tuner_instance_list; /* configuration settings */ - const struct au8522_config *config; + struct au8522_config config; struct dvb_frontend frontend; diff --git a/drivers/media/dvb-frontends/bsbe1-d01a.h b/drivers/media/dvb-frontends/bsbe1-d01a.h index 7ed3c424178c..baaf89e768cf 100644 --- a/drivers/media/dvb-frontends/bsbe1-d01a.h +++ b/drivers/media/dvb-frontends/bsbe1-d01a.h @@ -21,7 +21,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #ifndef BSBE1_D01A_H diff --git a/drivers/media/dvb-frontends/bsbe1.h b/drivers/media/dvb-frontends/bsbe1.h index 53e4d0dbb745..4ad766154741 100644 --- a/drivers/media/dvb-frontends/bsbe1.h +++ b/drivers/media/dvb-frontends/bsbe1.h @@ -19,7 +19,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #ifndef BSBE1_H diff --git a/drivers/media/dvb-frontends/bsru6.h b/drivers/media/dvb-frontends/bsru6.h index c2a578e1314d..275c1782597d 100644 --- a/drivers/media/dvb-frontends/bsru6.h +++ b/drivers/media/dvb-frontends/bsru6.h @@ -19,7 +19,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #ifndef BSRU6_H diff --git a/drivers/media/dvb-frontends/isl6405.c b/drivers/media/dvb-frontends/isl6405.c index b46450a10b80..6913cd687b4d 100644 --- a/drivers/media/dvb-frontends/isl6405.c +++ b/drivers/media/dvb-frontends/isl6405.c @@ -22,7 +22,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #include <linux/delay.h> #include <linux/errno.h> diff --git a/drivers/media/dvb-frontends/isl6405.h b/drivers/media/dvb-frontends/isl6405.h index 3c148b830bd1..4a23d3bdf3e6 100644 --- a/drivers/media/dvb-frontends/isl6405.h +++ b/drivers/media/dvb-frontends/isl6405.h @@ -22,7 +22,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #ifndef _ISL6405_H diff --git a/drivers/media/dvb-frontends/isl6421.c b/drivers/media/dvb-frontends/isl6421.c index 3a4d4606a426..0b6d3837d5de 100644 --- a/drivers/media/dvb-frontends/isl6421.c +++ b/drivers/media/dvb-frontends/isl6421.c @@ -22,7 +22,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #include <linux/delay.h> #include <linux/errno.h> diff --git a/drivers/media/dvb-frontends/isl6421.h b/drivers/media/dvb-frontends/isl6421.h index 3273597833fd..00f9874ca5a2 100644 --- a/drivers/media/dvb-frontends/isl6421.h +++ b/drivers/media/dvb-frontends/isl6421.h @@ -22,7 +22,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #ifndef _ISL6421_H diff --git a/drivers/media/dvb-frontends/lnbp21.c b/drivers/media/dvb-frontends/lnbp21.c index 4aca0fb9a8a7..6261460d93a7 100644 --- a/drivers/media/dvb-frontends/lnbp21.c +++ b/drivers/media/dvb-frontends/lnbp21.c @@ -22,7 +22,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #include <linux/delay.h> #include <linux/errno.h> diff --git a/drivers/media/dvb-frontends/lnbp21.h b/drivers/media/dvb-frontends/lnbp21.h index a9b530de62a6..cd9101f6e579 100644 --- a/drivers/media/dvb-frontends/lnbp21.h +++ b/drivers/media/dvb-frontends/lnbp21.h @@ -21,7 +21,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #ifndef _LNBP21_H diff --git a/drivers/media/dvb-frontends/lnbp22.c b/drivers/media/dvb-frontends/lnbp22.c index d7ca0fdd0084..5c5fd04fd4a7 100644 --- a/drivers/media/dvb-frontends/lnbp22.c +++ b/drivers/media/dvb-frontends/lnbp22.c @@ -22,7 +22,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #include <linux/delay.h> #include <linux/errno.h> diff --git a/drivers/media/dvb-frontends/lnbp22.h b/drivers/media/dvb-frontends/lnbp22.h index 628148385182..5d01d92814c2 100644 --- a/drivers/media/dvb-frontends/lnbp22.h +++ b/drivers/media/dvb-frontends/lnbp22.h @@ -22,7 +22,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org + * the project's page is at https://linuxtv.org */ #ifndef _LNBP22_H diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 78b87b260d74..10f2119935da 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -976,7 +976,8 @@ static int rtl2832_regmap_read(void *context, const void *reg_buf, ret = __i2c_transfer(client->adapter, msg, 2); if (ret != 2) { - dev_warn(&client->dev, "i2c reg read failed %d\n", ret); + dev_warn(&client->dev, "i2c reg read failed %d reg %02x\n", + ret, *(u8 *)reg_buf); if (ret >= 0) ret = -EREMOTEIO; return ret; @@ -999,7 +1000,8 @@ static int rtl2832_regmap_write(void *context, const void *data, size_t count) ret = __i2c_transfer(client->adapter, msg, 1); if (ret != 1) { - dev_warn(&client->dev, "i2c reg write failed %d\n", ret); + dev_warn(&client->dev, "i2c reg write failed %d reg %02x\n", + ret, *(u8 *)data); if (ret >= 0) ret = -EREMOTEIO; return ret; @@ -1028,7 +1030,8 @@ static int rtl2832_regmap_gather_write(void *context, const void *reg, ret = __i2c_transfer(client->adapter, msg, 1); if (ret != 1) { - dev_warn(&client->dev, "i2c reg write failed %d\n", ret); + dev_warn(&client->dev, "i2c reg write failed %d reg %02x\n", + ret, *(u8 const *)reg); if (ret >= 0) ret = -EREMOTEIO; return ret; @@ -1097,18 +1100,6 @@ static int rtl2832_enable_slave_ts(struct i2c_client *client) if (ret) goto err; - ret = rtl2832_bulk_write(client, 0x022, "\x01", 1); - if (ret) - goto err; - - ret = rtl2832_bulk_write(client, 0x026, "\x1f", 1); - if (ret) - goto err; - - ret = rtl2832_bulk_write(client, 0x027, "\xff", 1); - if (ret) - goto err; - ret = rtl2832_bulk_write(client, 0x192, "\x7f\xf7\xff", 3); if (ret) goto err; diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index dcd8d94c1037..b860f02a4e55 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -310,7 +310,7 @@ static void rtl2832_sdr_urb_complete(struct urb *urb) len = rtl2832_sdr_convert_stream(dev, ptr, urb->transfer_buffer, urb->actual_length); vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len); - v4l2_get_timestamp(&fbuf->vb.timestamp); + fbuf->vb.vb2_buf.timestamp = ktime_get_ns(); fbuf->vb.sequence = dev->sequence++; vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); } @@ -490,7 +490,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh, /* Videobuf2 operations */ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, + unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index 7c2eeee69757..1cf6e52e0105 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -1,21 +1,21 @@ /* - Driver for Silicon Labs Si2161 DVB-T and Si2165 DVB-C/-T Demodulator - - Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org> - - 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. - - 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. - - References: - http://www.silabs.com/Support%20Documents/TechnicalDocs/Si2165-short.pdf -*/ + * Driver for Silicon Labs Si2161 DVB-T and Si2165 DVB-C/-T Demodulator + * + * Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org> + * + * 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. + * + * 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. + * + * References: + * http://www.silabs.com/Support%20Documents/TechnicalDocs/Si2165-short.pdf + */ #include <linux/delay.h> #include <linux/errno.h> @@ -31,16 +31,18 @@ #include "si2165_priv.h" #include "si2165.h" -/* Hauppauge WinTV-HVR-930C-HD B130 / PCTV QuatroStick 521e 1113xx - * uses 16 MHz xtal */ - -/* Hauppauge WinTV-HVR-930C-HD B131 / PCTV QuatroStick 522e 1114xx - * uses 24 MHz clock provided by tuner */ +/* + * Hauppauge WinTV-HVR-930C-HD B130 / PCTV QuatroStick 521e 1113xx + * uses 16 MHz xtal + * + * Hauppauge WinTV-HVR-930C-HD B131 / PCTV QuatroStick 522e 1114xx + * uses 24 MHz clock provided by tuner + */ struct si2165_state { struct i2c_adapter *i2c; - struct dvb_frontend frontend; + struct dvb_frontend fe; struct si2165_config config; @@ -241,6 +243,27 @@ err: return ret; } +#define REG16(reg, val) { (reg), (val) & 0xff }, { (reg)+1, (val)>>8 & 0xff } +struct si2165_reg_value_pair { + u16 reg; + u8 val; +}; + +static int si2165_write_reg_list(struct si2165_state *state, + const struct si2165_reg_value_pair *regs, + int count) +{ + int i; + int ret; + + for (i = 0; i < count; i++) { + ret = si2165_writereg8(state, regs[i].reg, regs[i].val); + if (ret < 0) + return ret; + } + return 0; +} + static int si2165_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s) { @@ -258,8 +281,10 @@ static int si2165_init_pll(struct si2165_state *state) u8 divl = 12; u8 buf[4]; - /* hardcoded values can be deleted if calculation is verified - * or it yields the same values as the windows driver */ + /* + * hardcoded values can be deleted if calculation is verified + * or it yields the same values as the windows driver + */ switch (ref_freq_Hz) { case 16000000u: divn = 56; @@ -274,8 +299,10 @@ static int si2165_init_pll(struct si2165_state *state) if (ref_freq_Hz > 16000000u) divr = 2; - /* now select divn and divp such that - * fvco is in 1624..1824 MHz */ + /* + * now select divn and divp such that + * fvco is in 1624..1824 MHz + */ if (1624000000u * divr > ref_freq_Hz * 2u * 63u) divp = 4; @@ -341,10 +368,12 @@ static int si2165_upload_firmware_block(struct si2165_state *state, if (len % 4 != 0) return -EINVAL; - deb_fw_load("si2165_upload_firmware_block called with len=0x%x offset=0x%x blockcount=0x%x\n", + deb_fw_load( + "si2165_upload_firmware_block called with len=0x%x offset=0x%x blockcount=0x%x\n", len, offset, block_count); while (offset+12 <= len && cur_block < block_count) { - deb_fw_load("si2165_upload_firmware_block in while len=0x%x offset=0x%x cur_block=0x%x blockcount=0x%x\n", + deb_fw_load( + "si2165_upload_firmware_block in while len=0x%x offset=0x%x cur_block=0x%x blockcount=0x%x\n", len, offset, cur_block, block_count); wordcount = data[offset]; if (wordcount < 1 || data[offset+1] || @@ -383,7 +412,8 @@ static int si2165_upload_firmware_block(struct si2165_state *state, cur_block++; } - deb_fw_load("si2165_upload_firmware_block after while len=0x%x offset=0x%x cur_block=0x%x blockcount=0x%x\n", + deb_fw_load( + "si2165_upload_firmware_block after while len=0x%x offset=0x%x cur_block=0x%x blockcount=0x%x\n", len, offset, cur_block, block_count); if (poffset) @@ -633,7 +663,7 @@ static int si2165_init(struct dvb_frontend *fe) goto error; /* ber_pkt */ - ret = si2165_writereg16(state, 0x0470 , 0x7530); + ret = si2165_writereg16(state, 0x0470, 0x7530); if (ret < 0) goto error; @@ -660,22 +690,19 @@ static int si2165_init(struct dvb_frontend *fe) goto error; } - /* write adc values after each reset*/ - ret = si2165_writereg8(state, 0x012a, 0x46); - if (ret < 0) - goto error; - ret = si2165_writereg8(state, 0x012c, 0x00); + /* ts output config */ + ret = si2165_writereg8(state, 0x04e4, 0x20); if (ret < 0) - goto error; - ret = si2165_writereg8(state, 0x012e, 0x0a); + return ret; + ret = si2165_writereg16(state, 0x04ef, 0x00fe); if (ret < 0) - goto error; - ret = si2165_writereg8(state, 0x012f, 0xff); + return ret; + ret = si2165_writereg24(state, 0x04f4, 0x555555); if (ret < 0) - goto error; - ret = si2165_writereg8(state, 0x0123, 0x70); + return ret; + ret = si2165_writereg8(state, 0x04e5, 0x01); if (ret < 0) - goto error; + return ret; return 0; error: @@ -733,16 +760,26 @@ static int si2165_set_oversamp(struct si2165_state *state, u32 dvb_rate) do_div(oversamp, dvb_rate); reg_value = oversamp & 0x3fffffff; - /* oversamp, usbdump contained 0x03100000; */ + dprintk("%s: Write oversamp=%#x\n", __func__, reg_value); return si2165_writereg32(state, 0x00e4, reg_value); } -static int si2165_set_if_freq_shift(struct si2165_state *state, u32 IF) +static int si2165_set_if_freq_shift(struct si2165_state *state) { + struct dvb_frontend *fe = &state->fe; u64 if_freq_shift; s32 reg_value = 0; u32 fe_clk = si2165_get_fe_clk(state); + u32 IF = 0; + if (!fe->ops.tuner_ops.get_if_frequency) { + dev_err(&state->i2c->dev, + "%s: Error: get_if_frequency() not defined at tuner. Can't work without it!\n", + KBUILD_MODNAME); + return -EINVAL; + } + + fe->ops.tuner_ops.get_if_frequency(fe, &IF); if_freq_shift = IF; if_freq_shift <<= 29; @@ -758,25 +795,39 @@ static int si2165_set_if_freq_shift(struct si2165_state *state, u32 IF) return si2165_writereg32(state, 0x00e8, reg_value); } -static int si2165_set_parameters(struct dvb_frontend *fe) +static const struct si2165_reg_value_pair dvbt_regs[] = { + /* standard = DVB-T */ + { 0x00ec, 0x01 }, + { 0x08f8, 0x00 }, + /* impulsive_noise_remover */ + { 0x031c, 0x01 }, + { 0x00cb, 0x00 }, + /* agc2 */ + { 0x016e, 0x41 }, + { 0x016c, 0x0e }, + { 0x016d, 0x10 }, + /* agc */ + { 0x015b, 0x03 }, + { 0x0150, 0x78 }, + /* agc */ + { 0x01a0, 0x78 }, + { 0x01c8, 0x68 }, + /* freq_sync_range */ + REG16(0x030c, 0x0064), + /* gp_reg0 */ + { 0x0387, 0x00 } +}; + +static int si2165_set_frontend_dvbt(struct dvb_frontend *fe) { int ret; struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct si2165_state *state = fe->demodulator_priv; - u8 val[3]; - u32 IF; u32 dvb_rate = 0; u16 bw10k; dprintk("%s: called\n", __func__); - if (!fe->ops.tuner_ops.get_if_frequency) { - dev_err(&state->i2c->dev, - "%s: Error: get_if_frequency() not defined at tuner. Can't work without it!\n", - KBUILD_MODNAME); - return -EINVAL; - } - if (!state->has_dvbt) return -EINVAL; @@ -788,34 +839,10 @@ static int si2165_set_parameters(struct dvb_frontend *fe) bw10k = 800; } - /* standard = DVB-T */ - ret = si2165_writereg8(state, 0x00ec, 0x01); - if (ret < 0) - return ret; ret = si2165_adjust_pll_divl(state, 12); if (ret < 0) return ret; - fe->ops.tuner_ops.get_if_frequency(fe, &IF); - ret = si2165_set_if_freq_shift(state, IF); - if (ret < 0) - return ret; - ret = si2165_writereg8(state, 0x08f8, 0x00); - if (ret < 0) - return ret; - /* ts output config */ - ret = si2165_writereg8(state, 0x04e4, 0x20); - if (ret < 0) - return ret; - ret = si2165_writereg16(state, 0x04ef, 0x00fe); - if (ret < 0) - return ret; - ret = si2165_writereg24(state, 0x04f4, 0x555555); - if (ret < 0) - return ret; - ret = si2165_writereg8(state, 0x04e5, 0x01); - if (ret < 0) - return ret; /* bandwidth in 10KHz steps */ ret = si2165_writereg16(state, 0x0308, bw10k); if (ret < 0) @@ -823,48 +850,115 @@ static int si2165_set_parameters(struct dvb_frontend *fe) ret = si2165_set_oversamp(state, dvb_rate); if (ret < 0) return ret; - /* impulsive_noise_remover */ - ret = si2165_writereg8(state, 0x031c, 0x01); - if (ret < 0) - return ret; - ret = si2165_writereg8(state, 0x00cb, 0x00); + + ret = si2165_write_reg_list(state, dvbt_regs, ARRAY_SIZE(dvbt_regs)); if (ret < 0) return ret; + + return 0; +} + +static const struct si2165_reg_value_pair dvbc_regs[] = { + /* standard = DVB-C */ + { 0x00ec, 0x05 }, + { 0x08f8, 0x00 }, + /* agc2 */ - ret = si2165_writereg8(state, 0x016e, 0x41); - if (ret < 0) - return ret; - ret = si2165_writereg8(state, 0x016c, 0x0e); - if (ret < 0) - return ret; - ret = si2165_writereg8(state, 0x016d, 0x10); - if (ret < 0) - return ret; + { 0x016e, 0x50 }, + { 0x016c, 0x0e }, + { 0x016d, 0x10 }, /* agc */ - ret = si2165_writereg8(state, 0x015b, 0x03); - if (ret < 0) - return ret; - ret = si2165_writereg8(state, 0x0150, 0x78); - if (ret < 0) - return ret; + { 0x015b, 0x03 }, + { 0x0150, 0x68 }, /* agc */ - ret = si2165_writereg8(state, 0x01a0, 0x78); + { 0x01a0, 0x68 }, + { 0x01c8, 0x50 }, + + { 0x0278, 0x0d }, + + { 0x023a, 0x05 }, + { 0x0261, 0x09 }, + REG16(0x0350, 0x3e80), + { 0x02f4, 0x00 }, + + { 0x00cb, 0x01 }, + REG16(0x024c, 0x0000), + REG16(0x027c, 0x0000), + { 0x0232, 0x03 }, + { 0x02f4, 0x0b }, + { 0x018b, 0x00 }, +}; + +static int si2165_set_frontend_dvbc(struct dvb_frontend *fe) +{ + struct si2165_state *state = fe->demodulator_priv; + int ret; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + const u32 dvb_rate = p->symbol_rate; + const u32 bw_hz = p->bandwidth_hz; + + if (!state->has_dvbc) + return -EINVAL; + + if (dvb_rate == 0) + return -EINVAL; + + ret = si2165_adjust_pll_divl(state, 14); if (ret < 0) return ret; - ret = si2165_writereg8(state, 0x01c8, 0x68); + + /* Oversampling */ + ret = si2165_set_oversamp(state, dvb_rate); if (ret < 0) return ret; - /* freq_sync_range */ - ret = si2165_writereg16(state, 0x030c, 0x0064); + + ret = si2165_writereg32(state, 0x00c4, bw_hz); if (ret < 0) return ret; - /* gp_reg0 */ - ret = si2165_readreg8(state, 0x0387, val); + + ret = si2165_write_reg_list(state, dvbc_regs, ARRAY_SIZE(dvbc_regs)); if (ret < 0) return ret; - ret = si2165_writereg8(state, 0x0387, 0x00); + + return 0; +} + +static const struct si2165_reg_value_pair agc_rewrite[] = { + { 0x012a, 0x46 }, + { 0x012c, 0x00 }, + { 0x012e, 0x0a }, + { 0x012f, 0xff }, + { 0x0123, 0x70 } +}; + +static int si2165_set_frontend(struct dvb_frontend *fe) +{ + struct si2165_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + u32 delsys = p->delivery_system; + int ret; + u8 val[3]; + + /* initial setting of if freq shift */ + ret = si2165_set_if_freq_shift(state); if (ret < 0) return ret; + + switch (delsys) { + case SYS_DVBT: + ret = si2165_set_frontend_dvbt(fe); + if (ret < 0) + return ret; + break; + case SYS_DVBC_ANNEX_A: + ret = si2165_set_frontend_dvbc(fe); + if (ret < 0) + return ret; + break; + default: + return -EINVAL; + } + /* dsp_addr_jump */ ret = si2165_writereg32(state, 0x0348, 0xf4000000); if (ret < 0) @@ -874,8 +968,7 @@ static int si2165_set_parameters(struct dvb_frontend *fe) fe->ops.tuner_ops.set_params(fe); /* recalc if_freq_shift if IF might has changed */ - fe->ops.tuner_ops.get_if_frequency(fe, &IF); - ret = si2165_set_if_freq_shift(state, IF); + ret = si2165_set_if_freq_shift(state); if (ret < 0) return ret; @@ -886,6 +979,7 @@ static int si2165_set_parameters(struct dvb_frontend *fe) ret = si2165_writereg8(state, 0x0341, 0x00); if (ret < 0) return ret; + /* reset all */ ret = si2165_writereg8(state, 0x00c0, 0x00); if (ret < 0) @@ -894,6 +988,13 @@ static int si2165_set_parameters(struct dvb_frontend *fe) ret = si2165_writereg32(state, 0x0384, 0x00000000); if (ret < 0) return ret; + + /* write adc values after each reset*/ + ret = si2165_write_reg_list(state, agc_rewrite, + ARRAY_SIZE(agc_rewrite)); + if (ret < 0) + return ret; + /* start_synchro */ ret = si2165_writereg8(state, 0x02e0, 0x01); if (ret < 0) @@ -917,7 +1018,12 @@ static void si2165_release(struct dvb_frontend *fe) static struct dvb_frontend_ops si2165_ops = { .info = { .name = "Silicon Labs ", - .caps = FE_CAN_FEC_1_2 | + /* For DVB-C */ + .symbol_rate_min = 1000000, + .symbol_rate_max = 7200000, + /* For DVB-T */ + .frequency_stepsize = 166667, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | @@ -930,7 +1036,6 @@ static struct dvb_frontend_ops si2165_ops = { FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | FE_CAN_MUTE_TS | @@ -943,7 +1048,7 @@ static struct dvb_frontend_ops si2165_ops = { .init = si2165_init, .sleep = si2165_sleep, - .set_frontend = si2165_set_parameters, + .set_frontend = si2165_set_frontend, .read_status = si2165_read_status, .release = si2165_release, @@ -979,9 +1084,9 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config, } /* create dvb_frontend */ - memcpy(&state->frontend.ops, &si2165_ops, + memcpy(&state->fe.ops, &si2165_ops, sizeof(struct dvb_frontend_ops)); - state->frontend.demodulator_priv = state; + state->fe.demodulator_priv = state; /* powerup */ io_ret = si2165_writereg8(state, 0x0000, state->config.chip_mode); @@ -1033,20 +1138,22 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config, KBUILD_MODNAME, chip_name, rev_char, state->chip_type, state->chip_revcode); - strlcat(state->frontend.ops.info.name, chip_name, - sizeof(state->frontend.ops.info.name)); + strlcat(state->fe.ops.info.name, chip_name, + sizeof(state->fe.ops.info.name)); n = 0; if (state->has_dvbt) { - state->frontend.ops.delsys[n++] = SYS_DVBT; - strlcat(state->frontend.ops.info.name, " DVB-T", - sizeof(state->frontend.ops.info.name)); + state->fe.ops.delsys[n++] = SYS_DVBT; + strlcat(state->fe.ops.info.name, " DVB-T", + sizeof(state->fe.ops.info.name)); + } + if (state->has_dvbc) { + state->fe.ops.delsys[n++] = SYS_DVBC_ANNEX_A; + strlcat(state->fe.ops.info.name, " DVB-C", + sizeof(state->fe.ops.info.name)); } - if (state->has_dvbc) - dev_warn(&state->i2c->dev, "%s: DVB-C is not yet supported.\n", - KBUILD_MODNAME); - return &state->frontend; + return &state->fe; error: kfree(state); diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c index 4ef8a5c7003e..c978c801c7aa 100644 --- a/drivers/media/dvb-frontends/stb6100.c +++ b/drivers/media/dvb-frontends/stb6100.c @@ -252,6 +252,7 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) { int rc; u8 f; + u32 bw; struct stb6100_state *state = fe->tuner_priv; rc = stb6100_read_reg(state, STB6100_F); @@ -259,9 +260,9 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) return rc; f = rc & STB6100_F_F; - state->status.bandwidth = (f + 5) * 2000; /* x2 for ZIF */ + bw = (f + 5) * 2000; /* x2 for ZIF */ - *bandwidth = state->bandwidth = state->status.bandwidth * 1000; + *bandwidth = state->bandwidth = bw * 1000; dprintk(verbose, FE_DEBUG, 1, "bandwidth = %u Hz", state->bandwidth); return 0; } @@ -495,68 +496,28 @@ static int stb6100_sleep(struct dvb_frontend *fe) static int stb6100_init(struct dvb_frontend *fe) { struct stb6100_state *state = fe->tuner_priv; - struct tuner_state *status = &state->status; + int refclk = 27000000; /* Hz */ - status->tunerstep = 125000; - status->ifreq = 0; - status->refclock = 27000000; /* Hz */ - status->iqsense = 1; - status->bandwidth = 36000; /* kHz */ - state->bandwidth = status->bandwidth * 1000; /* Hz */ - state->reference = status->refclock / 1000; /* kHz */ + /* + * iqsense = 1 + * tunerstep = 125000 + */ + state->bandwidth = 36000000; /* Hz */ + state->reference = refclk / 1000; /* kHz */ /* Set default bandwidth. Modified, PN 13-May-10 */ return 0; } -static int stb6100_get_state(struct dvb_frontend *fe, - enum tuner_param param, - struct tuner_state *state) +static int stb6100_set_params(struct dvb_frontend *fe) { - switch (param) { - case DVBFE_TUNER_FREQUENCY: - stb6100_get_frequency(fe, &state->frequency); - break; - case DVBFE_TUNER_TUNERSTEP: - break; - case DVBFE_TUNER_IFFREQ: - break; - case DVBFE_TUNER_BANDWIDTH: - stb6100_get_bandwidth(fe, &state->bandwidth); - break; - case DVBFE_TUNER_REFCLOCK: - break; - default: - break; - } + struct dtv_frontend_properties *c = &fe->dtv_property_cache; - return 0; -} + if (c->frequency > 0) + stb6100_set_frequency(fe, c->frequency); -static int stb6100_set_state(struct dvb_frontend *fe, - enum tuner_param param, - struct tuner_state *state) -{ - struct stb6100_state *tstate = fe->tuner_priv; - - switch (param) { - case DVBFE_TUNER_FREQUENCY: - stb6100_set_frequency(fe, state->frequency); - tstate->frequency = state->frequency; - break; - case DVBFE_TUNER_TUNERSTEP: - break; - case DVBFE_TUNER_IFFREQ: - break; - case DVBFE_TUNER_BANDWIDTH: - stb6100_set_bandwidth(fe, state->bandwidth); - tstate->bandwidth = state->bandwidth; - break; - case DVBFE_TUNER_REFCLOCK: - break; - default: - break; - } + if (c->bandwidth_hz > 0) + stb6100_set_bandwidth(fe, c->bandwidth_hz); return 0; } @@ -572,8 +533,9 @@ static struct dvb_tuner_ops stb6100_ops = { .init = stb6100_init, .sleep = stb6100_sleep, .get_status = stb6100_get_status, - .get_state = stb6100_get_state, - .set_state = stb6100_set_state, + .set_params = stb6100_set_params, + .get_frequency = stb6100_get_frequency, + .get_bandwidth = stb6100_get_bandwidth, .release = stb6100_release }; diff --git a/drivers/media/dvb-frontends/stb6100.h b/drivers/media/dvb-frontends/stb6100.h index 218c8188865d..f7b468b6dc26 100644 --- a/drivers/media/dvb-frontends/stb6100.h +++ b/drivers/media/dvb-frontends/stb6100.h @@ -86,7 +86,6 @@ struct stb6100_state { const struct stb6100_config *config; struct dvb_tuner_ops ops; struct dvb_frontend *frontend; - struct tuner_state status; u32 frequency; u32 srate; diff --git a/drivers/media/dvb-frontends/stb6100_cfg.h b/drivers/media/dvb-frontends/stb6100_cfg.h index 6edc15365847..2ef67aa768b9 100644 --- a/drivers/media/dvb-frontends/stb6100_cfg.h +++ b/drivers/media/dvb-frontends/stb6100_cfg.h @@ -19,20 +19,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/dvb/frontend.h> +#include "dvb_frontend.h" + static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency) { struct dvb_frontend_ops *frontend_ops = &fe->ops; struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state t_state; int err = 0; - if (tuner_ops->get_state) { - err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state); + if (tuner_ops->get_frequency) { + err = tuner_ops->get_frequency(fe, frequency); if (err < 0) { printk("%s: Invalid parameter\n", __func__); return err; } - *frequency = t_state.frequency; } return 0; } @@ -41,13 +42,16 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) { struct dvb_frontend_ops *frontend_ops = &fe->ops; struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state t_state; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u32 bw = c->bandwidth_hz; int err = 0; - t_state.frequency = frequency; + c->frequency = frequency; + c->bandwidth_hz = 0; /* Don't adjust the bandwidth */ - if (tuner_ops->set_state) { - err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state); + if (tuner_ops->set_params) { + err = tuner_ops->set_params(fe); + c->bandwidth_hz = bw; if (err < 0) { printk("%s: Invalid parameter\n", __func__); return err; @@ -60,16 +64,14 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) { struct dvb_frontend_ops *frontend_ops = &fe->ops; struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state t_state; int err = 0; - if (tuner_ops->get_state) { - err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state); + if (tuner_ops->get_bandwidth) { + err = tuner_ops->get_bandwidth(fe, bandwidth); if (err < 0) { printk("%s: Invalid parameter\n", __func__); return err; } - *bandwidth = t_state.bandwidth; } return 0; } @@ -78,13 +80,16 @@ static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) { struct dvb_frontend_ops *frontend_ops = &fe->ops; struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state t_state; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u32 freq = c->frequency; int err = 0; - t_state.bandwidth = bandwidth; + c->bandwidth_hz = bandwidth; + c->frequency = 0; /* Don't adjust the frequency */ - if (tuner_ops->set_state) { - err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state); + if (tuner_ops->set_params) { + err = tuner_ops->set_params(fe); + c->frequency = freq; if (err < 0) { printk("%s: Invalid parameter\n", __func__); return err; diff --git a/drivers/media/dvb-frontends/stb6100_proc.h b/drivers/media/dvb-frontends/stb6100_proc.h index bd8a0ec9e2cc..50ffa21e3871 100644 --- a/drivers/media/dvb-frontends/stb6100_proc.h +++ b/drivers/media/dvb-frontends/stb6100_proc.h @@ -17,27 +17,27 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/dvb/frontend.h> +#include "dvb_frontend.h" + static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency) { struct dvb_frontend_ops *frontend_ops = &fe->ops; struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state state; int err = 0; - if (tuner_ops->get_state) { + if (tuner_ops->get_frequency) { if (frontend_ops->i2c_gate_ctrl) frontend_ops->i2c_gate_ctrl(fe, 1); - err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &state); + err = tuner_ops->get_frequency(fe, frequency); if (err < 0) { - printk(KERN_ERR "%s: Invalid parameter\n", __func__); + printk("%s: Invalid parameter\n", __func__); return err; } if (frontend_ops->i2c_gate_ctrl) frontend_ops->i2c_gate_ctrl(fe, 0); - - *frequency = state.frequency; } return 0; @@ -47,18 +47,21 @@ static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency) { struct dvb_frontend_ops *frontend_ops = &fe->ops; struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state state; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u32 bw = c->bandwidth_hz; int err = 0; - state.frequency = frequency; + c->frequency = frequency; + c->bandwidth_hz = 0; /* Don't adjust the bandwidth */ - if (tuner_ops->set_state) { + if (tuner_ops->set_params) { if (frontend_ops->i2c_gate_ctrl) frontend_ops->i2c_gate_ctrl(fe, 1); - err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &state); + err = tuner_ops->set_params(fe); + c->bandwidth_hz = bw; if (err < 0) { - printk(KERN_ERR "%s: Invalid parameter\n", __func__); + printk("%s: Invalid parameter\n", __func__); return err; } @@ -74,14 +77,13 @@ static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth) { struct dvb_frontend_ops *frontend_ops = &fe->ops; struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state state; int err = 0; - if (tuner_ops->get_state) { + if (tuner_ops->get_bandwidth) { if (frontend_ops->i2c_gate_ctrl) frontend_ops->i2c_gate_ctrl(fe, 1); - err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &state); + err = tuner_ops->get_bandwidth(fe, bandwidth); if (err < 0) { printk(KERN_ERR "%s: Invalid parameter\n", __func__); return err; @@ -89,8 +91,6 @@ static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth) if (frontend_ops->i2c_gate_ctrl) frontend_ops->i2c_gate_ctrl(fe, 0); - - *bandwidth = state.bandwidth; } return 0; @@ -100,16 +100,19 @@ static int stb6100_set_bandw(struct dvb_frontend *fe, u32 bandwidth) { struct dvb_frontend_ops *frontend_ops = &fe->ops; struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state state; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u32 freq = c->frequency; int err = 0; - state.bandwidth = bandwidth; + c->bandwidth_hz = bandwidth; + c->frequency = 0; /* Don't adjust the frequency */ - if (tuner_ops->set_state) { + if (tuner_ops->set_params) { if (frontend_ops->i2c_gate_ctrl) frontend_ops->i2c_gate_ctrl(fe, 1); - err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &state); + err = tuner_ops->set_params(fe); + c->frequency = freq; if (err < 0) { printk(KERN_ERR "%s: Invalid parameter\n", __func__); return err; diff --git a/drivers/media/dvb-frontends/tda665x.c b/drivers/media/dvb-frontends/tda665x.c index 63cc12378d9a..82f8cc534f33 100644 --- a/drivers/media/dvb-frontends/tda665x.c +++ b/drivers/media/dvb-frontends/tda665x.c @@ -66,26 +66,13 @@ exit: return err; } -static int tda665x_get_state(struct dvb_frontend *fe, - enum tuner_param param, - struct tuner_state *tstate) +static int tda665x_get_frequency(struct dvb_frontend *fe, u32 *frequency) { struct tda665x_state *state = fe->tuner_priv; - int err = 0; - switch (param) { - case DVBFE_TUNER_FREQUENCY: - tstate->frequency = state->frequency; - break; - case DVBFE_TUNER_BANDWIDTH: - break; - default: - printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param); - err = -EINVAL; - break; - } + *frequency = state->frequency; - return err; + return 0; } static int tda665x_get_status(struct dvb_frontend *fe, u32 *status) @@ -111,9 +98,8 @@ exit: return err; } -static int tda665x_set_state(struct dvb_frontend *fe, - enum tuner_param param, - struct tuner_state *tstate) +static int tda665x_set_frequency(struct dvb_frontend *fe, + u32 new_frequency) { struct tda665x_state *state = fe->tuner_priv; const struct tda665x_config *config = state->config; @@ -121,88 +107,96 @@ static int tda665x_set_state(struct dvb_frontend *fe, u8 buf[4]; int err = 0; - if (param & DVBFE_TUNER_FREQUENCY) { - - frequency = tstate->frequency; - if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) { - printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); - return -EINVAL; - } - - frequency += config->frequency_offst; - frequency *= config->ref_multiplier; - frequency += config->ref_divider >> 1; - frequency /= config->ref_divider; - - buf[0] = (u8) ((frequency & 0x7f00) >> 8); - buf[1] = (u8) (frequency & 0x00ff) >> 0; - buf[2] = 0x80 | 0x40 | 0x02; - buf[3] = 0x00; - - /* restore frequency */ - frequency = tstate->frequency; - - if (frequency < 153000000) { - /* VHF-L */ - buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */ - if (frequency < 68000000) - buf[3] |= 0x40; /* 83uA */ - if (frequency < 1040000000) - buf[3] |= 0x60; /* 122uA */ - if (frequency < 1250000000) - buf[3] |= 0x80; /* 163uA */ - else - buf[3] |= 0xa0; /* 254uA */ - } else if (frequency < 438000000) { - /* VHF-H */ - buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */ - if (frequency < 230000000) - buf[3] |= 0x40; - if (frequency < 300000000) - buf[3] |= 0x60; - else - buf[3] |= 0x80; - } else { - /* UHF */ - buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */ - if (frequency < 470000000) - buf[3] |= 0x60; - if (frequency < 526000000) - buf[3] |= 0x80; - else - buf[3] |= 0xa0; - } - - /* Set params */ - err = tda665x_write(state, buf, 5); - if (err < 0) - goto exit; - - /* sleep for some time */ - printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__); - msleep(20); - /* check status */ - err = tda665x_get_status(fe, &status); - if (err < 0) - goto exit; - - if (status == 1) { - printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", __func__, status); - state->frequency = frequency; /* cache successful state */ - } else { - printk(KERN_ERR "%s: No Phase lock: status=%d\n", __func__, status); - } - } else { - printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param); + if ((new_frequency < config->frequency_max) + || (new_frequency > config->frequency_min)) { + printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", + __func__, new_frequency); return -EINVAL; } + frequency = new_frequency; + + frequency += config->frequency_offst; + frequency *= config->ref_multiplier; + frequency += config->ref_divider >> 1; + frequency /= config->ref_divider; + + buf[0] = (u8) ((frequency & 0x7f00) >> 8); + buf[1] = (u8) (frequency & 0x00ff) >> 0; + buf[2] = 0x80 | 0x40 | 0x02; + buf[3] = 0x00; + + /* restore frequency */ + frequency = new_frequency; + + if (frequency < 153000000) { + /* VHF-L */ + buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */ + if (frequency < 68000000) + buf[3] |= 0x40; /* 83uA */ + if (frequency < 1040000000) + buf[3] |= 0x60; /* 122uA */ + if (frequency < 1250000000) + buf[3] |= 0x80; /* 163uA */ + else + buf[3] |= 0xa0; /* 254uA */ + } else if (frequency < 438000000) { + /* VHF-H */ + buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */ + if (frequency < 230000000) + buf[3] |= 0x40; + if (frequency < 300000000) + buf[3] |= 0x60; + else + buf[3] |= 0x80; + } else { + /* UHF */ + buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */ + if (frequency < 470000000) + buf[3] |= 0x60; + if (frequency < 526000000) + buf[3] |= 0x80; + else + buf[3] |= 0xa0; + } + + /* Set params */ + err = tda665x_write(state, buf, 5); + if (err < 0) + goto exit; + + /* sleep for some time */ + printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__); + msleep(20); + /* check status */ + err = tda665x_get_status(fe, &status); + if (err < 0) + goto exit; + + if (status == 1) { + printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", + __func__, status); + state->frequency = frequency; /* cache successful state */ + } else { + printk(KERN_ERR "%s: No Phase lock: status=%d\n", + __func__, status); + } + return 0; exit: printk(KERN_ERR "%s: I/O Error\n", __func__); return err; } +static int tda665x_set_params(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + + tda665x_set_frequency(fe, c->frequency); + + return 0; +} + static int tda665x_release(struct dvb_frontend *fe) { struct tda665x_state *state = fe->tuner_priv; @@ -213,10 +207,9 @@ static int tda665x_release(struct dvb_frontend *fe) } static struct dvb_tuner_ops tda665x_ops = { - - .set_state = tda665x_set_state, - .get_state = tda665x_get_state, .get_status = tda665x_get_status, + .set_params = tda665x_set_params, + .get_frequency = tda665x_get_frequency, .release = tda665x_release }; diff --git a/drivers/media/dvb-frontends/tda8261.c b/drivers/media/dvb-frontends/tda8261.c index 19c488814e5c..3285b1bc4642 100644 --- a/drivers/media/dvb-frontends/tda8261.c +++ b/drivers/media/dvb-frontends/tda8261.c @@ -83,88 +83,71 @@ static int tda8261_get_status(struct dvb_frontend *fe, u32 *status) static const u32 div_tab[] = { 2000, 1000, 500, 250, 125 }; /* kHz */ static const u8 ref_div[] = { 0x00, 0x01, 0x02, 0x05, 0x07 }; -static int tda8261_get_state(struct dvb_frontend *fe, - enum tuner_param param, - struct tuner_state *tstate) +static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency) { struct tda8261_state *state = fe->tuner_priv; - int err = 0; - switch (param) { - case DVBFE_TUNER_FREQUENCY: - tstate->frequency = state->frequency; - break; - case DVBFE_TUNER_BANDWIDTH: - tstate->bandwidth = 40000000; /* FIXME! need to calculate Bandwidth */ - break; - default: - pr_err("%s: Unknown parameter (param=%d)\n", __func__, param); - err = -EINVAL; - break; - } + *frequency = state->frequency; - return err; + return 0; } -static int tda8261_set_state(struct dvb_frontend *fe, - enum tuner_param param, - struct tuner_state *tstate) +static int tda8261_set_params(struct dvb_frontend *fe) { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct tda8261_state *state = fe->tuner_priv; const struct tda8261_config *config = state->config; u32 frequency, N, status = 0; u8 buf[4]; int err = 0; - if (param & DVBFE_TUNER_FREQUENCY) { - /** - * N = Max VCO Frequency / Channel Spacing - * Max VCO Frequency = VCO frequency + (channel spacing - 1) - * (to account for half channel spacing on either side) - */ - frequency = tstate->frequency; - if ((frequency < 950000) || (frequency > 2150000)) { - pr_warn("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); - return -EINVAL; - } - N = (frequency + (div_tab[config->step_size] - 1)) / div_tab[config->step_size]; - pr_debug("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n", - __func__, config->step_size, div_tab[config->step_size], N, N); - - buf[0] = (N >> 8) & 0xff; - buf[1] = N & 0xff; - buf[2] = (0x01 << 7) | ((ref_div[config->step_size] & 0x07) << 1); - - if (frequency < 1450000) - buf[3] = 0x00; - else if (frequency < 2000000) - buf[3] = 0x40; - else if (frequency < 2150000) - buf[3] = 0x80; - - /* Set params */ - if ((err = tda8261_write(state, buf)) < 0) { - pr_err("%s: I/O Error\n", __func__); - return err; - } - /* sleep for some time */ - pr_debug("%s: Waiting to Phase LOCK\n", __func__); - msleep(20); - /* check status */ - if ((err = tda8261_get_status(fe, &status)) < 0) { - pr_err("%s: I/O Error\n", __func__); - return err; - } - if (status == 1) { - pr_debug("%s: Tuner Phase locked: status=%d\n", __func__, status); - state->frequency = frequency; /* cache successful state */ - } else { - pr_debug("%s: No Phase lock: status=%d\n", __func__, status); - } - } else { - pr_err("%s: Unknown parameter (param=%d)\n", __func__, param); + /* + * N = Max VCO Frequency / Channel Spacing + * Max VCO Frequency = VCO frequency + (channel spacing - 1) + * (to account for half channel spacing on either side) + */ + frequency = c->frequency; + if ((frequency < 950000) || (frequency > 2150000)) { + pr_warn("%s: Frequency beyond limits, frequency=%d\n", + __func__, frequency); return -EINVAL; } + N = (frequency + (div_tab[config->step_size] - 1)) / div_tab[config->step_size]; + pr_debug("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n", + __func__, config->step_size, div_tab[config->step_size], N, N); + + buf[0] = (N >> 8) & 0xff; + buf[1] = N & 0xff; + buf[2] = (0x01 << 7) | ((ref_div[config->step_size] & 0x07) << 1); + + if (frequency < 1450000) + buf[3] = 0x00; + else if (frequency < 2000000) + buf[3] = 0x40; + else if (frequency < 2150000) + buf[3] = 0x80; + + /* Set params */ + err = tda8261_write(state, buf); + if (err < 0) { + pr_err("%s: I/O Error\n", __func__); + return err; + } + /* sleep for some time */ + pr_debug("%s: Waiting to Phase LOCK\n", __func__); + msleep(20); + /* check status */ + if ((err = tda8261_get_status(fe, &status)) < 0) { + pr_err("%s: I/O Error\n", __func__); + return err; + } + if (status == 1) { + pr_debug("%s: Tuner Phase locked: status=%d\n", __func__, + status); + state->frequency = frequency; /* cache successful state */ + } else { + pr_debug("%s: No Phase lock: status=%d\n", __func__, status); + } return 0; } @@ -182,14 +165,13 @@ static struct dvb_tuner_ops tda8261_ops = { .info = { .name = "TDA8261", -// .tuner_name = NULL, .frequency_min = 950000, .frequency_max = 2150000, .frequency_step = 0 }, - .set_state = tda8261_set_state, - .get_state = tda8261_get_state, + .set_params = tda8261_set_params, + .get_frequency = tda8261_get_frequency, .get_status = tda8261_get_status, .release = tda8261_release }; @@ -210,10 +192,7 @@ struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe, fe->ops.tuner_ops = tda8261_ops; fe->ops.tuner_ops.info.frequency_step = div_tab[config->step_size]; -// fe->ops.tuner_ops.tuner_name = &config->buf; -// printk("%s: Attaching %s TDA8261 8PSK/QPSK tuner\n", -// __func__, fe->ops.tuner_ops.tuner_name); pr_info("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__); return fe; diff --git a/drivers/media/dvb-frontends/tda8261_cfg.h b/drivers/media/dvb-frontends/tda8261_cfg.h index 04a19e14ee5a..fe527ff84df4 100644 --- a/drivers/media/dvb-frontends/tda8261_cfg.h +++ b/drivers/media/dvb-frontends/tda8261_cfg.h @@ -21,17 +21,15 @@ static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency) { struct dvb_frontend_ops *frontend_ops = &fe->ops; struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state t_state; int err = 0; - if (tuner_ops->get_state) { - err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state); + if (tuner_ops->get_frequency) { + err = tuner_ops->get_frequency(fe, frequency); if (err < 0) { - printk("%s: Invalid parameter\n", __func__); + pr_err("%s: Invalid parameter\n", __func__); return err; } - *frequency = t_state.frequency; - printk("%s: Frequency=%d\n", __func__, t_state.frequency); + pr_debug("%s: Frequency=%d\n", __func__, *frequency); } return 0; } @@ -40,37 +38,24 @@ static int tda8261_set_frequency(struct dvb_frontend *fe, u32 frequency) { struct dvb_frontend_ops *frontend_ops = &fe->ops; struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state t_state; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; int err = 0; - t_state.frequency = frequency; - - if (tuner_ops->set_state) { - err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state); + if (tuner_ops->set_params) { + err = tuner_ops->set_params(fe); if (err < 0) { - printk("%s: Invalid parameter\n", __func__); + pr_err("%s: Invalid parameter\n", __func__); return err; } } - printk("%s: Frequency=%d\n", __func__, t_state.frequency); + pr_debug("%s: Frequency=%d\n", __func__, c->frequency); return 0; } static int tda8261_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) { - struct dvb_frontend_ops *frontend_ops = &fe->ops; - struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; - struct tuner_state t_state; - int err = 0; + /* FIXME! need to calculate Bandwidth */ + *bandwidth = 40000000; - if (tuner_ops->get_state) { - err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state); - if (err < 0) { - printk("%s: Invalid parameter\n", __func__); - return err; - } - *bandwidth = t_state.bandwidth; - printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth); - } return 0; } diff --git a/drivers/media/dvb-frontends/tdhd1.h b/drivers/media/dvb-frontends/tdhd1.h index 17750985db0c..2b9e8732c802 100644 --- a/drivers/media/dvb-frontends/tdhd1.h +++ b/drivers/media/dvb-frontends/tdhd1.h @@ -20,7 +20,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * The project's page is at http://www.linuxtv.org + * The project's page is at https://linuxtv.org */ #ifndef TDHD1_H diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 521bbf1b29bc..993dc50c12db 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -83,6 +83,16 @@ config VIDEO_MSP3400 To compile this driver as a module, choose M here: the module will be called msp3400. +config VIDEO_CS3308 + tristate "Cirrus Logic CS3308 audio ADC" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Cirrus Logic CS3308 High Performance 8-Channel + Analog Volume Control + + To compile this driver as a module, choose M here: the + module will be called cs3308. + config VIDEO_CS5345 tristate "Cirrus Logic CS5345 audio ADC" depends on VIDEO_V4L2 && I2C diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 07db257abfc1..94f2c99e890d 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o obj-$(CONFIG_VIDEO_TW2804) += tw2804.o obj-$(CONFIG_VIDEO_TW9903) += tw9903.o obj-$(CONFIG_VIDEO_TW9906) += tw9906.o +obj-$(CONFIG_VIDEO_CS3308) += cs3308.o obj-$(CONFIG_VIDEO_CS5345) += cs5345.o obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o obj-$(CONFIG_VIDEO_M52790) += m52790.o diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index 69094ab047b1..0494a7896aa2 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -35,7 +35,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-dv-timings.h> #include <media/v4l2-ctrls.h> -#include <media/ad9389b.h> +#include <media/i2c/ad9389b.h> static int debug; module_param(debug, int, 0644); diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index 5dd39775d6ca..f00745bbe471 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -37,7 +37,7 @@ #include <linux/slab.h> #include <linux/of.h> #include <linux/gpio/consumer.h> -#include <media/adp1653.h> +#include <media/i2c/adp1653.h> #include <media/v4l2-device.h> #define TIMEOUT_MAX 820000 diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index f82c8aa164fa..3c3c4bfe3866 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -1112,7 +1112,7 @@ static int init_device(struct adv7180_state *state) mutex_lock(&state->mutex); adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES); - usleep_range(2000, 10000); + usleep_range(5000, 10000); ret = state->chip_info->init(state); if (ret) diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index e2dd1617662f..2bec737881e9 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -27,7 +27,7 @@ #include <linux/types.h> #include <linux/videodev2.h> -#include <media/adv7183.h> +#include <media/i2c/adv7183.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index f89d0afcd964..11f9029433cf 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c @@ -28,7 +28,7 @@ #include <linux/of.h> #include <linux/of_graph.h> -#include <media/adv7343.h> +#include <media/i2c/adv7343.h> #include <media/v4l2-async.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> diff --git a/drivers/media/i2c/adv7393.c b/drivers/media/i2c/adv7393.c index 0215f95c2245..76d987476e35 100644 --- a/drivers/media/i2c/adv7393.c +++ b/drivers/media/i2c/adv7393.c @@ -31,7 +31,7 @@ #include <linux/videodev2.h> #include <linux/uaccess.h> -#include <media/adv7393.h> +#include <media/i2c/adv7393.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index e4900df1140b..eeb2cd823c4d 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -32,7 +32,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-dv-timings.h> -#include <media/adv7511.h> +#include <media/i2c/adv7511.h> static int debug; module_param(debug, int, 0644); @@ -1116,7 +1116,7 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd, adv7511_wr_and_or(sd, 0x55, 0x9f, y << 5); adv7511_wr_and_or(sd, 0x56, 0x3f, c << 6); adv7511_wr_and_or(sd, 0x57, 0x83, (ec << 4) | (q << 2)); - adv7511_wr_and_or(sd, 0x59, 0x0f, yq << 4); + adv7511_wr_and_or(sd, 0x59, 0x3f, yq << 6); adv7511_wr_and_or(sd, 0x4a, 0xff, 1); return 0; diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 5631ec004eed..745286225655 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -39,7 +39,7 @@ #include <linux/workqueue.h> #include <linux/regmap.h> -#include <media/adv7604.h> +#include <media/i2c/adv7604.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-event.h> @@ -905,7 +905,7 @@ static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, for (i = 0; predef_vid_timings[i].timings.bt.width; i++) { if (!v4l2_match_dv_timings(timings, &predef_vid_timings[i].timings, - is_digital_input(sd) ? 250000 : 1000000)) + is_digital_input(sd) ? 250000 : 1000000, false)) continue; io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */ io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) + @@ -1479,7 +1479,7 @@ static void adv76xx_fill_optional_dv_timings_fields(struct v4l2_subdev *sd, for (i = 0; adv76xx_timings[i].bt.width; i++) { if (v4l2_match_dv_timings(timings, &adv76xx_timings[i], - is_digital_input(sd) ? 250000 : 1000000)) { + is_digital_input(sd) ? 250000 : 1000000, false)) { *timings = adv76xx_timings[i]; break; } @@ -1644,7 +1644,7 @@ static int adv76xx_s_dv_timings(struct v4l2_subdev *sd, if (!timings) return -EINVAL; - if (v4l2_match_dv_timings(&state->timings, timings, 0)) { + if (v4l2_match_dv_timings(&state->timings, timings, 0, false)) { v4l2_dbg(1, debug, sd, "%s: no change\n", __func__); return 0; } diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index b7269b8f040d..69378e4914b6 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -43,7 +43,7 @@ #include <media/v4l2-event.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-dv-timings.h> -#include <media/adv7842.h> +#include <media/i2c/adv7842.h> static int debug; module_param(debug, int, 0644); @@ -155,7 +155,7 @@ static bool adv7842_check_dv_timings(const struct v4l2_dv_timings *t, void *hdl) int i; for (i = 0; adv7842_timings_exceptions[i].bt.width; i++) - if (v4l2_match_dv_timings(t, adv7842_timings_exceptions + i, 0)) + if (v4l2_match_dv_timings(t, adv7842_timings_exceptions + i, 0, false)) return false; return true; } @@ -1008,7 +1008,7 @@ static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, for (i = 0; predef_vid_timings[i].timings.bt.width; i++) { if (!v4l2_match_dv_timings(timings, &predef_vid_timings[i].timings, - is_digital_input(sd) ? 250000 : 1000000)) + is_digital_input(sd) ? 250000 : 1000000, false)) continue; /* video std */ io_write(sd, 0x00, predef_vid_timings[i].vid_std); @@ -1659,7 +1659,7 @@ static int adv7842_s_dv_timings(struct v4l2_subdev *sd, if (state->mode == ADV7842_MODE_SDP) return -ENODATA; - if (v4l2_match_dv_timings(&state->timings, timings, 0)) { + if (v4l2_match_dv_timings(&state->timings, timings, 0, false)) { v4l2_dbg(1, debug, sd, "%s: no change\n", __func__); return 0; } diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c index d3b965ec3bbc..d9f2b6b76d59 100644 --- a/drivers/media/i2c/ak881x.c +++ b/drivers/media/i2c/ak881x.c @@ -15,7 +15,7 @@ #include <linux/videodev2.h> #include <linux/module.h> -#include <media/ak881x.h> +#include <media/i2c/ak881x.h> #include <media/v4l2-common.h> #include <media/v4l2-device.h> diff --git a/drivers/media/i2c/as3645a.c b/drivers/media/i2c/as3645a.c index 301084b07887..29a2e7034aa6 100644 --- a/drivers/media/i2c/as3645a.c +++ b/drivers/media/i2c/as3645a.c @@ -31,7 +31,7 @@ #include <linux/mutex.h> #include <linux/slab.h> -#include <media/as3645a.h> +#include <media/i2c/as3645a.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> diff --git a/drivers/media/i2c/bt819.c b/drivers/media/i2c/bt819.c index e00e3104d448..7907bcfbaed3 100644 --- a/drivers/media/i2c/bt819.c +++ b/drivers/media/i2c/bt819.c @@ -37,7 +37,7 @@ #include <linux/slab.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/bt819.h> +#include <media/i2c/bt819.h> MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); diff --git a/drivers/media/i2c/cs3308.c b/drivers/media/i2c/cs3308.c new file mode 100644 index 000000000000..d28b4f37fe5f --- /dev/null +++ b/drivers/media/i2c/cs3308.c @@ -0,0 +1,138 @@ +/* + * Cirrus Logic cs3308 8-Channel Analog Volume Control + * + * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com> + * Copyright (C) 2012 Steven Toth <stoth@kernellabs.com> + * + * Derived from cs5345.c Copyright (C) 2007 Hans Verkuil + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/videodev2.h> +#include <media/v4l2-device.h> + +MODULE_DESCRIPTION("i2c device driver for cs3308 8-channel volume control"); +MODULE_AUTHOR("Devin Heitmueller"); +MODULE_LICENSE("GPL"); + +static inline int cs3308_write(struct v4l2_subdev *sd, u8 reg, u8 value) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return i2c_smbus_write_byte_data(client, reg, value); +} + +static inline int cs3308_read(struct v4l2_subdev *sd, u8 reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return i2c_smbus_read_byte_data(client, reg); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int cs3308_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +{ + reg->val = cs3308_read(sd, reg->reg & 0xffff); + reg->size = 1; + return 0; +} + +static int cs3308_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) +{ + cs3308_write(sd, reg->reg & 0xffff, reg->val & 0xff); + return 0; +} +#endif + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops cs3308_core_ops = { +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = cs3308_g_register, + .s_register = cs3308_s_register, +#endif +}; + +static const struct v4l2_subdev_ops cs3308_ops = { + .core = &cs3308_core_ops, +}; + +/* ----------------------------------------------------------------------- */ + +static int cs3308_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct v4l2_subdev *sd; + unsigned i; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + if ((i2c_smbus_read_byte_data(client, 0x1c) & 0xf0) != 0xe0) + return -ENODEV; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + + sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + + v4l2_i2c_subdev_init(sd, client, &cs3308_ops); + + /* Set some reasonable defaults */ + cs3308_write(sd, 0x0d, 0x00); /* Power up all channels */ + cs3308_write(sd, 0x0e, 0x00); /* Master Power */ + cs3308_write(sd, 0x0b, 0x00); /* Device Configuration */ + /* Set volume for each channel */ + for (i = 1; i <= 8; i++) + cs3308_write(sd, i, 0xd2); + cs3308_write(sd, 0x0a, 0x00); /* Unmute all channels */ + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static int cs3308_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(sd); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static const struct i2c_device_id cs3308_id[] = { + { "cs3308", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cs3308_id); + +static struct i2c_driver cs3308_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "cs3308", + }, + .probe = cs3308_probe, + .remove = cs3308_remove, + .id_table = cs3308_id, +}; + +module_i2c_driver(cs3308_driver); diff --git a/drivers/media/i2c/cx25840/cx25840-audio.c b/drivers/media/i2c/cx25840/cx25840-audio.c index 34b96c7cfd62..baf3d9c8710e 100644 --- a/drivers/media/i2c/cx25840/cx25840-audio.c +++ b/drivers/media/i2c/cx25840/cx25840-audio.c @@ -19,7 +19,7 @@ #include <linux/videodev2.h> #include <linux/i2c.h> #include <media/v4l2-common.h> -#include <media/cx25840.h> +#include <media/drv-intf/cx25840.h> #include "cx25840-core.h" diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index fe6eb78b6914..f2e2c34ddbbd 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -45,7 +45,7 @@ #include <linux/delay.h> #include <linux/math64.h> #include <media/v4l2-common.h> -#include <media/cx25840.h> +#include <media/drv-intf/cx25840.h> #include "cx25840-core.h" @@ -559,7 +559,10 @@ static void cx23885_initialize(struct i2c_client *client) cx25840_write4(client, 0x414, 0x00107d12); /* Chroma */ - cx25840_write4(client, 0x420, 0x3d008282); + if (is_cx23888(state)) + cx25840_write4(client, 0x418, 0x1d008282); + else + cx25840_write4(client, 0x420, 0x3d008282); /* * Aux PLL @@ -666,14 +669,17 @@ static void cx23885_initialize(struct i2c_client *client) cx25840_write4(client, 0x404, 0x0010253e); /* CC on - Undocumented Register */ - cx25840_write(client, 0x42f, 0x66); + cx25840_write(client, state->vbi_regs_offset + 0x42f, 0x66); /* HVR-1250 / HVR1850 DIF related */ /* Power everything up */ cx25840_write4(client, 0x130, 0x0); /* Undocumented */ - cx25840_write4(client, 0x478, 0x6628021F); + if (is_cx23888(state)) + cx25840_write4(client, 0x454, 0x6628021F); + else + cx25840_write4(client, 0x478, 0x6628021F); /* AFE_CLK_OUT_CTRL - Select the clock output source as output */ cx25840_write4(client, 0x144, 0x5); @@ -1106,31 +1112,15 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp cx25840_write4(client, 0x410, 0xffff0dbf); cx25840_write4(client, 0x414, 0x00137d03); - /* on the 887, 0x418 is HSCALE_CTRL, on the 888 it is - CHROMA_CTRL */ - if (is_cx23888(state)) - cx25840_write4(client, 0x418, 0x01008080); - else - cx25840_write4(client, 0x418, 0x01000000); + cx25840_write4(client, state->vbi_regs_offset + 0x42c, 0x42600000); + cx25840_write4(client, state->vbi_regs_offset + 0x430, 0x0000039b); + cx25840_write4(client, state->vbi_regs_offset + 0x438, 0x00000000); - cx25840_write4(client, 0x41c, 0x00000000); - - /* on the 887, 0x420 is CHROMA_CTRL, on the 888 it is - CRUSH_CTRL */ - if (is_cx23888(state)) - cx25840_write4(client, 0x420, 0x001c3e0f); - else - cx25840_write4(client, 0x420, 0x001c8282); - - cx25840_write4(client, 0x42c, 0x42600000); - cx25840_write4(client, 0x430, 0x0000039b); - cx25840_write4(client, 0x438, 0x00000000); - - cx25840_write4(client, 0x440, 0xF8E3E824); - cx25840_write4(client, 0x444, 0x401040dc); - cx25840_write4(client, 0x448, 0xcd3f02a0); - cx25840_write4(client, 0x44c, 0x161f1000); - cx25840_write4(client, 0x450, 0x00000802); + cx25840_write4(client, state->vbi_regs_offset + 0x440, 0xF8E3E824); + cx25840_write4(client, state->vbi_regs_offset + 0x444, 0x401040dc); + cx25840_write4(client, state->vbi_regs_offset + 0x448, 0xcd3f02a0); + cx25840_write4(client, state->vbi_regs_offset + 0x44c, 0x161f1000); + cx25840_write4(client, state->vbi_regs_offset + 0x450, 0x00000802); cx25840_write4(client, 0x91c, 0x01000000); cx25840_write4(client, 0x8e0, 0x03063870); @@ -1400,8 +1390,14 @@ static int cx25840_set_fmt(struct v4l2_subdev *sd, Vlines = fmt->height + (is_50Hz ? 4 : 7); + /* + * We keep 1 margin for the Vsrc < Vlines check since the + * cx23888 reports a Vsrc of 486 instead of 487 for the NTSC + * height. Without that margin the cx23885 fails in this + * check. + */ if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) || - (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { + (Vlines * 8 < Vsrc) || (Vsrc + 1 < Vlines)) { v4l_err(client, "%dx%d is not a valid size!\n", fmt->width, fmt->height); return -ERANGE; @@ -1426,14 +1422,20 @@ static int cx25840_set_fmt(struct v4l2_subdev *sd, fmt->width, fmt->height, HSC, VSC); /* HSCALE=HSC */ - cx25840_write(client, 0x418, HSC & 0xff); - cx25840_write(client, 0x419, (HSC >> 8) & 0xff); - cx25840_write(client, 0x41a, HSC >> 16); - /* VSCALE=VSC */ - cx25840_write(client, 0x41c, VSC & 0xff); - cx25840_write(client, 0x41d, VSC >> 8); - /* VS_INTRLACE=1 VFILT=filter */ - cx25840_write(client, 0x41e, 0x8 | filter); + if (is_cx23888(state)) { + cx25840_write4(client, 0x434, HSC | (1 << 24)); + /* VSCALE=VSC VS_INTRLACE=1 VFILT=filter */ + cx25840_write4(client, 0x438, VSC | (1 << 19) | (filter << 16)); + } else { + cx25840_write(client, 0x418, HSC & 0xff); + cx25840_write(client, 0x419, (HSC >> 8) & 0xff); + cx25840_write(client, 0x41a, HSC >> 16); + /* VSCALE=VSC */ + cx25840_write(client, 0x41c, VSC & 0xff); + cx25840_write(client, 0x41d, VSC >> 8); + /* VS_INTRLACE=1 VFILT=filter */ + cx25840_write(client, 0x41e, 0x8 | filter); + } return 0; } @@ -1714,26 +1716,27 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) v4l_dbg(1, cx25840_debug, client, "%s video output\n", enable ? "enable" : "disable"); + + /* + * It's not clear what should be done for these devices. + * The original code used the same addresses as for the cx25840, but + * those addresses do something else entirely on the cx2388x and + * cx231xx. Since it never did anything in the first place, just do + * nothing. + */ + if (is_cx2388x(state) || is_cx231xx(state)) + return 0; + if (enable) { - if (is_cx2388x(state) || is_cx231xx(state)) { - v = cx25840_read(client, 0x421) | 0x0b; - cx25840_write(client, 0x421, v); - } else { - v = cx25840_read(client, 0x115) | 0x0c; - cx25840_write(client, 0x115, v); - v = cx25840_read(client, 0x116) | 0x04; - cx25840_write(client, 0x116, v); - } + v = cx25840_read(client, 0x115) | 0x0c; + cx25840_write(client, 0x115, v); + v = cx25840_read(client, 0x116) | 0x04; + cx25840_write(client, 0x116, v); } else { - if (is_cx2388x(state) || is_cx231xx(state)) { - v = cx25840_read(client, 0x421) & ~(0x0b); - cx25840_write(client, 0x421, v); - } else { - v = cx25840_read(client, 0x115) & ~(0x0c); - cx25840_write(client, 0x115, v); - v = cx25840_read(client, 0x116) & ~(0x04); - cx25840_write(client, 0x116, v); - } + v = cx25840_read(client, 0x115) & ~(0x0c); + cx25840_write(client, 0x115, v); + v = cx25840_read(client, 0x116) & ~(0x04); + cx25840_write(client, 0x116, v); } return 0; } @@ -4974,7 +4977,7 @@ static void cx23888_std_setup(struct i2c_client *client) cx25840_write4(client, 0x4b4, 0x20524030); cx25840_write4(client, 0x47c, 0x010a8263); - if (std & V4L2_STD_NTSC) { + if (std & V4L2_STD_525_60) { v4l_dbg(1, cx25840_debug, client, "%s() Selecting NTSC", __func__); @@ -5264,6 +5267,8 @@ static int cx25840_probe(struct i2c_client *client, state->vbi_line_offset = 8; state->id = id; state->rev = device_id; + state->vbi_regs_offset = id == CX23888_AV ? 0x500 - 0x424 : 0; + state->std = V4L2_STD_NTSC_M; v4l2_ctrl_handler_init(&state->hdl, 9); v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); diff --git a/drivers/media/i2c/cx25840/cx25840-core.h b/drivers/media/i2c/cx25840/cx25840-core.h index fdea48ce0c03..254ef45ce41a 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.h +++ b/drivers/media/i2c/cx25840/cx25840-core.h @@ -69,6 +69,7 @@ struct cx25840_state { enum cx25840_model id; u32 rev; int is_initialized; + unsigned vbi_regs_offset; wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ struct work_struct fw_work; /* work entry for fw load */ struct cx25840_ir_state *ir_state; diff --git a/drivers/media/i2c/cx25840/cx25840-firmware.c b/drivers/media/i2c/cx25840/cx25840-firmware.c index 9bbb31adc29d..37e052923a87 100644 --- a/drivers/media/i2c/cx25840/cx25840-firmware.c +++ b/drivers/media/i2c/cx25840/cx25840-firmware.c @@ -19,7 +19,7 @@ #include <linux/i2c.h> #include <linux/firmware.h> #include <media/v4l2-common.h> -#include <media/cx25840.h> +#include <media/drv-intf/cx25840.h> #include "cx25840-core.h" diff --git a/drivers/media/i2c/cx25840/cx25840-ir.c b/drivers/media/i2c/cx25840/cx25840-ir.c index 4cf8f18bf097..4b782012cadc 100644 --- a/drivers/media/i2c/cx25840/cx25840-ir.c +++ b/drivers/media/i2c/cx25840/cx25840-ir.c @@ -24,7 +24,7 @@ #include <linux/slab.h> #include <linux/kfifo.h> #include <linux/module.h> -#include <media/cx25840.h> +#include <media/drv-intf/cx25840.h> #include <media/rc-core.h> #include "cx25840-core.h" diff --git a/drivers/media/i2c/cx25840/cx25840-vbi.c b/drivers/media/i2c/cx25840/cx25840-vbi.c index c39e91dc1137..0470bb6128e1 100644 --- a/drivers/media/i2c/cx25840/cx25840-vbi.c +++ b/drivers/media/i2c/cx25840/cx25840-vbi.c @@ -19,7 +19,7 @@ #include <linux/videodev2.h> #include <linux/i2c.h> #include <media/v4l2-common.h> -#include <media/cx25840.h> +#include <media/drv-intf/cx25840.h> #include "cx25840-core.h" @@ -104,7 +104,8 @@ int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format * if (is_pal) { for (i = 7; i <= 23; i++) { - u8 v = cx25840_read(client, 0x424 + i - 7); + u8 v = cx25840_read(client, + state->vbi_regs_offset + 0x424 + i - 7); svbi->service_lines[0][i] = lcr2vbi[v >> 4]; svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; @@ -113,7 +114,8 @@ int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format * } } else { for (i = 10; i <= 21; i++) { - u8 v = cx25840_read(client, 0x424 + i - 10); + u8 v = cx25840_read(client, + state->vbi_regs_offset + 0x424 + i - 10); svbi->service_lines[0][i] = lcr2vbi[v >> 4]; svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; @@ -135,7 +137,10 @@ int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) cx25840_std_setup(client); /* VBI Offset */ - cx25840_write(client, 0x47f, vbi_offset); + if (is_cx23888(state)) + cx25840_write(client, 0x54f, vbi_offset); + else + cx25840_write(client, 0x47f, vbi_offset); cx25840_write(client, 0x404, 0x2e); return 0; } @@ -158,7 +163,10 @@ int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format * /* Sliced VBI */ cx25840_write(client, 0x404, 0x32); /* Ancillary data */ cx25840_write(client, 0x406, 0x13); - cx25840_write(client, 0x47f, vbi_offset); + if (is_cx23888(state)) + cx25840_write(client, 0x54f, vbi_offset); + else + cx25840_write(client, 0x47f, vbi_offset); if (is_pal) { for (i = 0; i <= 6; i++) @@ -194,17 +202,23 @@ int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format * } if (is_pal) { - for (x = 1, i = 0x424; i <= 0x434; i++, x++) + for (x = 1, i = state->vbi_regs_offset + 0x424; + i <= state->vbi_regs_offset + 0x434; i++, x++) cx25840_write(client, i, lcr[6 + x]); } else { - for (x = 1, i = 0x424; i <= 0x430; i++, x++) + for (x = 1, i = state->vbi_regs_offset + 0x424; + i <= state->vbi_regs_offset + 0x430; i++, x++) cx25840_write(client, i, lcr[9 + x]); - for (i = 0x431; i <= 0x434; i++) + for (i = state->vbi_regs_offset + 0x431; + i <= state->vbi_regs_offset + 0x434; i++) cx25840_write(client, i, 0); } - cx25840_write(client, 0x43c, 0x16); - cx25840_write(client, 0x474, is_pal ? 0x2a : 0x22); + cx25840_write(client, state->vbi_regs_offset + 0x43c, 0x16); + if (is_cx23888(state)) + cx25840_write(client, 0x428, is_pal ? 0x2a : 0x22); + else + cx25840_write(client, 0x474, is_pal ? 0x2a : 0x22); return 0; } diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 728d2cc8a3e7..830491960add 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -47,7 +47,7 @@ #include <linux/workqueue.h> #include <media/rc-core.h> -#include <media/ir-kbd-i2c.h> +#include <media/i2c/ir-kbd-i2c.h> /* ----------------------------------------------------------------------- */ /* insmod parameters */ diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c index d9ece4b2d047..19ecb8801064 100644 --- a/drivers/media/i2c/lm3560.c +++ b/drivers/media/i2c/lm3560.c @@ -24,7 +24,7 @@ #include <linux/mutex.h> #include <linux/regmap.h> #include <linux/videodev2.h> -#include <media/lm3560.h> +#include <media/i2c/lm3560.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> diff --git a/drivers/media/i2c/lm3646.c b/drivers/media/i2c/lm3646.c index 626fb4679c02..7fbe6ff1c4f4 100644 --- a/drivers/media/i2c/lm3646.c +++ b/drivers/media/i2c/lm3646.c @@ -18,7 +18,7 @@ #include <linux/slab.h> #include <linux/regmap.h> #include <linux/videodev2.h> -#include <media/lm3646.h> +#include <media/i2c/lm3646.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> diff --git a/drivers/media/i2c/m52790.c b/drivers/media/i2c/m52790.c index 77eb07eb667e..81171d8e1c2c 100644 --- a/drivers/media/i2c/m52790.c +++ b/drivers/media/i2c/m52790.c @@ -27,7 +27,7 @@ #include <asm/uaccess.h> #include <linux/i2c.h> #include <linux/videodev2.h> -#include <media/m52790.h> +#include <media/i2c/m52790.h> #include <media/v4l2-device.h> MODULE_DESCRIPTION("i2c device driver for m52790 A/V switch"); diff --git a/drivers/media/i2c/m5mols/m5mols_capture.c b/drivers/media/i2c/m5mols/m5mols_capture.c index 1a03d02bd4d1..a0cd6dc32eb0 100644 --- a/drivers/media/i2c/m5mols/m5mols_capture.c +++ b/drivers/media/i2c/m5mols/m5mols_capture.c @@ -25,8 +25,8 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> -#include <media/m5mols.h> -#include <media/exynos-fimc.h> +#include <media/i2c/m5mols.h> +#include <media/drv-intf/exynos-fimc.h> #include "m5mols.h" #include "m5mols_reg.h" diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 6404c0d93e7a..f8993933416e 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -25,7 +25,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> -#include <media/m5mols.h> +#include <media/i2c/m5mols.h> #include "m5mols.h" #include "m5mols_reg.h" diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index bdb94000ba5a..a84561d0d4a8 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -56,8 +56,8 @@ #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> -#include <media/msp3400.h> -#include <media/tvaudio.h> +#include <media/drv-intf/msp3400.h> +#include <media/i2c/tvaudio.h> #include "msp3400-driver.h" /* ---------------------------------------------------------------------- */ diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h index fbe5e0715f93..6cae21366ed5 100644 --- a/drivers/media/i2c/msp3400-driver.h +++ b/drivers/media/i2c/msp3400-driver.h @@ -4,7 +4,7 @@ #ifndef MSP3400_DRIVER_H #define MSP3400_DRIVER_H -#include <media/msp3400.h> +#include <media/drv-intf/msp3400.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> diff --git a/drivers/media/i2c/msp3400-kthreads.c b/drivers/media/i2c/msp3400-kthreads.c index f8b51714f2f9..17120804fab7 100644 --- a/drivers/media/i2c/msp3400-kthreads.c +++ b/drivers/media/i2c/msp3400-kthreads.c @@ -26,7 +26,7 @@ #include <linux/freezer.h> #include <linux/videodev2.h> #include <media/v4l2-common.h> -#include <media/msp3400.h> +#include <media/drv-intf/msp3400.h> #include <linux/kthread.h> #include <linux/suspend.h> #include "msp3400-driver.h" diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c index c7747bd0cabb..101cb26f9330 100644 --- a/drivers/media/i2c/mt9m032.c +++ b/drivers/media/i2c/mt9m032.c @@ -31,7 +31,7 @@ #include <linux/v4l2-mediabus.h> #include <media/media-entity.h> -#include <media/mt9m032.h> +#include <media/i2c/mt9m032.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> @@ -671,7 +671,7 @@ static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl) return 0; } -static struct v4l2_ctrl_ops mt9m032_ctrl_ops = { +static const struct v4l2_ctrl_ops mt9m032_ctrl_ops = { .s_ctrl = mt9m032_set_ctrl, .try_ctrl = mt9m032_try_ctrl, }; diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 0db15f528ac1..a3da0e977d0b 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -26,7 +26,7 @@ #include <linux/slab.h> #include <linux/videodev2.h> -#include <media/mt9p031.h> +#include <media/i2c/mt9p031.h> #include <media/v4l2-async.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> @@ -817,7 +817,7 @@ static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -static struct v4l2_ctrl_ops mt9p031_ctrl_ops = { +static const struct v4l2_ctrl_ops mt9p031_ctrl_ops = { .s_ctrl = mt9p031_s_ctrl, }; diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c index 8ae99f7f254c..b28fdff1d310 100644 --- a/drivers/media/i2c/mt9t001.c +++ b/drivers/media/i2c/mt9t001.c @@ -21,7 +21,7 @@ #include <linux/videodev2.h> #include <linux/v4l2-mediabus.h> -#include <media/mt9t001.h> +#include <media/i2c/mt9t001.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> @@ -626,7 +626,7 @@ static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -static struct v4l2_ctrl_ops mt9t001_ctrl_ops = { +static const struct v4l2_ctrl_ops mt9t001_ctrl_ops = { .s_ctrl = mt9t001_s_ctrl, }; diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index a4a5c39b599b..b9fea11d6b0b 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -13,7 +13,7 @@ #include <asm/div64.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/mt9v011.h> +#include <media/i2c/mt9v011.h> MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); MODULE_AUTHOR("Mauro Carvalho Chehab"); @@ -454,7 +454,7 @@ static int mt9v011_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -static struct v4l2_ctrl_ops mt9v011_ctrl_ops = { +static const struct v4l2_ctrl_ops mt9v011_ctrl_ops = { .s_ctrl = mt9v011_s_ctrl, }; diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index a68ce94ee097..1dbbd23fdfb0 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -25,7 +25,7 @@ #include <linux/v4l2-mediabus.h> #include <linux/module.h> -#include <media/mt9v032.h> +#include <media/i2c/mt9v032.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-of.h> @@ -703,7 +703,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -static struct v4l2_ctrl_ops mt9v032_ctrl_ops = { +static const struct v4l2_ctrl_ops mt9v032_ctrl_ops = { .s_ctrl = mt9v032_s_ctrl, }; diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c index f197b6cbd407..69e4f3031d8b 100644 --- a/drivers/media/i2c/noon010pc30.c +++ b/drivers/media/i2c/noon010pc30.c @@ -18,7 +18,7 @@ #include <linux/i2c.h> #include <linux/slab.h> #include <linux/regulator/consumer.h> -#include <media/noon010pc30.h> +#include <media/i2c/noon010pc30.h> #include <linux/videodev2.h> #include <linux/module.h> #include <media/v4l2-ctrls.h> diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 49109f4f5bb4..82c7ac1cc88e 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -37,7 +37,7 @@ #include <linux/videodev2.h> #include <media/media-entity.h> -#include <media/ov2659.h> +#include <media/i2c/ov2659.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> @@ -1249,7 +1249,7 @@ static int ov2659_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -static struct v4l2_ctrl_ops ov2659_ctrl_ops = { +static const struct v4l2_ctrl_ops ov2659_ctrl_ops = { .s_ctrl = ov2659_s_ctrl, }; diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index e1b5dc84c14e..56cfb5ca9c95 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -20,7 +20,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-mediabus.h> #include <media/v4l2-image-sizes.h> -#include <media/ov7670.h> +#include <media/i2c/ov7670.h> MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors"); diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index 1ee6a5527c38..9fe9006474b2 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -29,7 +29,7 @@ #include <media/v4l2-image-sizes.h> #include <media/v4l2-subdev.h> #include <media/v4l2-mediabus.h> -#include <media/ov9650.h> +#include <media/i2c/ov9650.h> static int debug; module_param(debug, int, 0644); diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 51b26010403c..25f5e79dc9bc 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -34,7 +34,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> #include <media/v4l2-mediabus.h> -#include <media/s5c73m3.h> +#include <media/i2c/s5c73m3.h> #include <media/v4l2-of.h> #include "s5c73m3.h" diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c index 8001cde1db1e..0a060339e516 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c @@ -32,7 +32,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> #include <media/v4l2-mediabus.h> -#include <media/s5c73m3.h> +#include <media/i2c/s5c73m3.h> #include "s5c73m3.h" diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c index 72ef9f936e6c..7d65b36434b1 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c @@ -37,6 +37,7 @@ enum spi_direction { SPI_DIR_RX, SPI_DIR_TX }; +MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids); static int spi_xmit(struct spi_device *spi_dev, void *addr, const int len, enum spi_direction dir) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h index 13aed59f0f5d..653f68e7ea07 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3.h +++ b/drivers/media/i2c/s5c73m3/s5c73m3.h @@ -23,7 +23,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-subdev.h> -#include <media/s5c73m3.h> +#include <media/i2c/s5c73m3.h> #define DRIVER_NAME "S5C73M3" diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c index 97084237275d..6757aca2cdab 100644 --- a/drivers/media/i2c/s5k4ecgx.c +++ b/drivers/media/i2c/s5k4ecgx.c @@ -27,7 +27,7 @@ #include <asm/unaligned.h> #include <media/media-entity.h> -#include <media/s5k4ecgx.h> +#include <media/i2c/s5k4ecgx.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-mediabus.h> diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index d0ad6a25bdab..60aaff7190d2 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c @@ -28,7 +28,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> #include <media/v4l2-mediabus.h> -#include <media/s5k6aa.h> +#include <media/i2c/s5k6aa.h> static int debug; module_param(debug, int, 0644); diff --git a/drivers/media/i2c/saa6588.c b/drivers/media/i2c/saa6588.c index 37e65f661d7a..89e458c23983 100644 --- a/drivers/media/i2c/saa6588.c +++ b/drivers/media/i2c/saa6588.c @@ -31,7 +31,7 @@ #include <linux/wait.h> #include <asm/uaccess.h> -#include <media/saa6588.h> +#include <media/i2c/saa6588.h> #include <media/v4l2-device.h> diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 91e75222c537..24d2b76dbe97 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -46,7 +46,7 @@ #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> #include <asm/div64.h> #define VRES_60HZ (480+16) diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c index a43d96da1017..8d94dcbf4366 100644 --- a/drivers/media/i2c/saa7127.c +++ b/drivers/media/i2c/saa7127.c @@ -54,7 +54,7 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/saa7127.h> +#include <media/i2c/saa7127.h> static int debug; static int test_image; diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h index ed010a8a49d7..f6af0cc4a256 100644 --- a/drivers/media/i2c/smiapp/smiapp.h +++ b/drivers/media/i2c/smiapp/smiapp.h @@ -22,7 +22,7 @@ #include <linux/mutex.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-subdev.h> -#include <media/smiapp.h> +#include <media/i2c/smiapp.h> #include "smiapp-pll.h" #include "smiapp-reg.h" diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c index 4fbdd1e9f7ee..2e14e52ba2e0 100644 --- a/drivers/media/i2c/soc_camera/mt9m001.c +++ b/drivers/media/i2c/soc_camera/mt9m001.c @@ -15,7 +15,7 @@ #include <linux/module.h> #include <media/soc_camera.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> #include <media/v4l2-clk.h> #include <media/v4l2-subdev.h> #include <media/v4l2-ctrls.h> diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c index 2f35d31ca58e..6a1b2a9f9a09 100644 --- a/drivers/media/i2c/soc_camera/mt9t112.c +++ b/drivers/media/i2c/soc_camera/mt9t112.c @@ -25,7 +25,7 @@ #include <linux/v4l2-mediabus.h> #include <linux/videodev2.h> -#include <media/mt9t112.h> +#include <media/i2c/mt9t112.h> #include <media/soc_camera.h> #include <media/v4l2-clk.h> #include <media/v4l2-common.h> diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index f31377408550..c2ba1fb3694d 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c @@ -15,9 +15,9 @@ #include <linux/log2.h> #include <linux/module.h> -#include <media/mt9v022.h> +#include <media/i2c/mt9v022.h> #include <media/soc_camera.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> #include <media/v4l2-subdev.h> #include <media/v4l2-clk.h> #include <media/v4l2-ctrls.h> diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c index f150a8bd94dc..a43410c1e254 100644 --- a/drivers/media/i2c/soc_camera/ov772x.c +++ b/drivers/media/i2c/soc_camera/ov772x.c @@ -24,7 +24,7 @@ #include <linux/v4l2-mediabus.h> #include <linux/videodev2.h> -#include <media/ov772x.h> +#include <media/i2c/ov772x.h> #include <media/soc_camera.h> #include <media/v4l2-clk.h> #include <media/v4l2-ctrls.h> diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c index c769cf663f84..aa7bfbb4ad71 100644 --- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c +++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c @@ -15,7 +15,7 @@ #include <linux/videodev2.h> #include <linux/module.h> -#include <media/rj54n1cb0c.h> +#include <media/i2c/rj54n1cb0c.h> #include <media/soc_camera.h> #include <media/v4l2-clk.h> #include <media/v4l2-subdev.h> diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c index e939c24bfd3c..06aff81787a7 100644 --- a/drivers/media/i2c/soc_camera/tw9910.c +++ b/drivers/media/i2c/soc_camera/tw9910.c @@ -26,7 +26,7 @@ #include <linux/videodev2.h> #include <media/soc_camera.h> -#include <media/tw9910.h> +#include <media/i2c/tw9910.h> #include <media/v4l2-clk.h> #include <media/v4l2-subdev.h> diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c index b04c09dd4bfb..0bf031b7e4fa 100644 --- a/drivers/media/i2c/sr030pc30.c +++ b/drivers/media/i2c/sr030pc30.c @@ -24,7 +24,7 @@ #include <media/v4l2-subdev.h> #include <media/v4l2-mediabus.h> #include <media/v4l2-ctrls.h> -#include <media/sr030pc30.h> +#include <media/i2c/sr030pc30.h> static int debug; module_param(debug, int, 0644); diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 9ef5baaf8646..77b801152ea5 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -42,7 +42,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> #include <media/v4l2-of.h> -#include <media/tc358743.h> +#include <media/i2c/tc358743.h> #include "tc358743_regs.h" @@ -862,7 +862,7 @@ static void tc358743_format_change(struct v4l2_subdev *sd) v4l2_dbg(1, debug, sd, "%s: Format changed. No signal\n", __func__); } else { - if (!v4l2_match_dv_timings(&state->timings, &timings, 0)) + if (!v4l2_match_dv_timings(&state->timings, &timings, 0, false)) enable_stream(sd, false); v4l2_print_dv_timings(sd->name, @@ -1366,7 +1366,7 @@ static int tc358743_s_dv_timings(struct v4l2_subdev *sd, v4l2_print_dv_timings(sd->name, "tc358743_s_dv_timings: ", timings, false); - if (v4l2_match_dv_timings(&state->timings, timings, 0)) { + if (v4l2_match_dv_timings(&state->timings, timings, 0, false)) { v4l2_dbg(1, debug, sd, "%s: no change\n", __func__); return 0; } diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index bda3a6540a60..5bbfcab01c75 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -25,7 +25,7 @@ #include <linux/module.h> #include <linux/slab.h> -#include <media/ths7303.h> +#include <media/i2c/ths7303.h> #include <media/v4l2-device.h> #define THS7303_CHANNEL_1 1 diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c index 2a8114a676fd..fece2a4339a1 100644 --- a/drivers/media/i2c/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c @@ -36,7 +36,7 @@ #include <linux/kthread.h> #include <linux/freezer.h> -#include <media/tvaudio.h> +#include <media/i2c/tvaudio.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index a93985a9b070..b5dba5b7ce3a 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -44,7 +44,7 @@ #include <media/v4l2-mediabus.h> #include <media/v4l2-of.h> #include <media/v4l2-ctrls.h> -#include <media/tvp514x.h> +#include <media/i2c/tvp514x.h> #include <media/media-entity.h> #include "tvp514x_regs.h" diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 3c5fb2509c47..6c3769d44b75 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -12,7 +12,7 @@ #include <linux/module.h> #include <media/v4l2-async.h> #include <media/v4l2-device.h> -#include <media/tvp5150.h> +#include <media/i2c/tvp5150.h> #include <media/v4l2-ctrls.h> #include "tvp5150_reg.h" diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index f617d8b745ee..772a3043ae3b 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -32,7 +32,7 @@ #include <linux/of.h> #include <linux/of_graph.h> #include <linux/v4l2-dv-timings.h> -#include <media/tvp7002.h> +#include <media/i2c/tvp7002.h> #include <media/v4l2-async.h> #include <media/v4l2-device.h> #include <media/v4l2-common.h> diff --git a/drivers/media/i2c/uda1342.c b/drivers/media/i2c/uda1342.c index 081786d176d0..8e17a83920d4 100644 --- a/drivers/media/i2c/uda1342.c +++ b/drivers/media/i2c/uda1342.c @@ -20,7 +20,7 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/uda1342.h> +#include <media/i2c/uda1342.h> #include <linux/slab.h> static int write_reg(struct i2c_client *client, int reg, int value) diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c index 2c0f955abc72..c03567e993cd 100644 --- a/drivers/media/i2c/upd64031a.c +++ b/drivers/media/i2c/upd64031a.c @@ -27,7 +27,7 @@ #include <linux/videodev2.h> #include <linux/slab.h> #include <media/v4l2-device.h> -#include <media/upd64031a.h> +#include <media/i2c/upd64031a.h> /* --------------------- read registers functions define -------------------- */ diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c index f2057a434060..77f122f2e3c9 100644 --- a/drivers/media/i2c/upd64083.c +++ b/drivers/media/i2c/upd64083.c @@ -27,7 +27,7 @@ #include <linux/videodev2.h> #include <linux/slab.h> #include <media/v4l2-device.h> -#include <media/upd64083.h> +#include <media/i2c/upd64083.h> MODULE_DESCRIPTION("uPD64083 driver"); MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil"); diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c index d33d2cd6d034..6e00f145b948 100644 --- a/drivers/media/i2c/wm8775.c +++ b/drivers/media/i2c/wm8775.c @@ -34,7 +34,7 @@ #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/wm8775.h> +#include <media/i2c/wm8775.h> MODULE_DESCRIPTION("wm8775 driver"); MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index 4654fb65ca21..8a17cc0bfa07 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c @@ -41,7 +41,7 @@ #include "bttvp.h" #include <media/v4l2-common.h> -#include <media/tvaudio.h> +#include <media/i2c/tvaudio.h> #include "bttv-audio-hook.h" /* fwd decl */ @@ -3808,7 +3808,7 @@ static void bttv_tea575x_set_direction(struct snd_tea575x *tea, bool output) gpio_inout(mask, (1 << gpio.clk) | (1 << gpio.wren)); } -static struct snd_tea575x_ops bttv_tea_ops = { +static const struct snd_tea575x_ops bttv_tea_ops = { .set_pins = bttv_tea575x_set_pins, .get_pins = bttv_tea575x_get_pins, .set_direction = bttv_tea575x_set_direction, diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 15a4ebc2844d..9400e996087b 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -50,15 +50,15 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/tvaudio.h> -#include <media/msp3400.h> +#include <media/i2c/tvaudio.h> +#include <media/drv-intf/msp3400.h> #include <linux/dma-mapping.h> #include <asm/io.h> #include <asm/byteorder.h> -#include <media/saa6588.h> +#include <media/i2c/saa6588.h> #define BTTV_VERSION "0.9.19" diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h index 31bf79d3b0d2..b1e0023f923c 100644 --- a/drivers/media/pci/bt8xx/bttvp.h +++ b/drivers/media/pci/bt8xx/bttvp.h @@ -41,8 +41,8 @@ #include <media/videobuf-dma-sg.h> #include <media/tveeprom.h> #include <media/rc-core.h> -#include <media/ir-kbd-i2c.h> -#include <media/tea575x.h> +#include <media/i2c/ir-kbd-i2c.h> +#include <media/drv-intf/tea575x.h> #include "bt848.h" #include "bttv.h" diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c index 8fed61ec712e..8d6f04fc8013 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.c +++ b/drivers/media/pci/cobalt/cobalt-driver.c @@ -21,9 +21,9 @@ */ #include <linux/delay.h> -#include <media/adv7604.h> -#include <media/adv7842.h> -#include <media/adv7511.h> +#include <media/i2c/adv7604.h> +#include <media/i2c/adv7842.h> +#include <media/i2c/adv7511.h> #include <media/v4l2-event.h> #include <media/v4l2-ctrls.h> diff --git a/drivers/media/pci/cobalt/cobalt-irq.c b/drivers/media/pci/cobalt/cobalt-irq.c index 3de26d0714b5..b190d4f81c6e 100644 --- a/drivers/media/pci/cobalt/cobalt-irq.c +++ b/drivers/media/pci/cobalt/cobalt-irq.c @@ -18,7 +18,7 @@ * SOFTWARE. */ -#include <media/adv7604.h> +#include <media/i2c/adv7604.h> #include "cobalt-driver.h" #include "cobalt-irq.h" @@ -134,7 +134,7 @@ done: skip = true; s->skip_first_frames--; } - v4l2_get_timestamp(&cb->vb.timestamp); + cb->vb.vb2_buf.timestamp = ktime_get_ns(); /* TODO: the sequence number should be read from the FPGA so we also know about dropped frames. */ cb->vb.sequence = s->sequence++; diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c index ff46e424262f..c0ba458f6cf3 100644 --- a/drivers/media/pci/cobalt/cobalt-v4l2.c +++ b/drivers/media/pci/cobalt/cobalt-v4l2.c @@ -29,8 +29,8 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> #include <media/v4l2-dv-timings.h> -#include <media/adv7604.h> -#include <media/adv7842.h> +#include <media/i2c/adv7604.h> +#include <media/i2c/adv7842.h> #include "cobalt-alsa.h" #include "cobalt-cpld.h" @@ -43,11 +43,10 @@ static const struct v4l2_dv_timings cea1080p60 = V4L2_DV_BT_CEA_1920X1080P60; /* vb2 DMA streaming ops */ -static int cobalt_queue_setup(struct vb2_queue *q, const void *parg, +static int cobalt_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct cobalt_stream *s = q->drv_priv; unsigned size = s->stride * s->height; @@ -55,14 +54,11 @@ static int cobalt_queue_setup(struct vb2_queue *q, const void *parg, *num_buffers = 3; if (*num_buffers > NR_BUFS) *num_buffers = NR_BUFS; + alloc_ctxs[0] = s->cobalt->alloc_ctx; + if (*num_planes) + return sizes[0] < size ? -EINVAL : 0; *num_planes = 1; - if (fmt) { - if (fmt->fmt.pix.sizeimage < size) - return -EINVAL; - size = fmt->fmt.pix.sizeimage; - } sizes[0] = size; - alloc_ctxs[0] = s->cobalt->alloc_ctx; return 0; } @@ -649,7 +645,7 @@ static int cobalt_s_dv_timings(struct file *file, void *priv_fh, return 0; } - if (v4l2_match_dv_timings(timings, &s->timings, 0)) + if (v4l2_match_dv_timings(timings, &s->timings, 0, false)) return 0; if (vb2_is_busy(&s->q)) diff --git a/drivers/media/pci/cx18/cx18-cards.c b/drivers/media/pci/cx18/cx18-cards.c index c07c849b1aaf..5e01ea441dc4 100644 --- a/drivers/media/pci/cx18/cx18-cards.c +++ b/drivers/media/pci/cx18/cx18-cards.c @@ -26,7 +26,7 @@ #include "cx18-cards.h" #include "cx18-av-core.h" #include "cx18-i2c.h" -#include <media/cs5345.h> +#include <media/i2c/cs5345.h> #define V4L2_STD_PAL_SECAM (V4L2_STD_PAL|V4L2_STD_SECAM) diff --git a/drivers/media/pci/cx18/cx18-controls.c b/drivers/media/pci/cx18/cx18-controls.c index 71227a155cba..adb5a8c72c06 100644 --- a/drivers/media/pci/cx18/cx18-controls.c +++ b/drivers/media/pci/cx18/cx18-controls.c @@ -126,7 +126,7 @@ static int cx18_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val) return 0; } -struct cx2341x_handler_ops cx18_cxhdl_ops = { +const struct cx2341x_handler_ops cx18_cxhdl_ops = { .s_audio_mode = cx18_s_audio_mode, .s_audio_sampling_freq = cx18_s_audio_sampling_freq, .s_video_encoding = cx18_s_video_encoding, diff --git a/drivers/media/pci/cx18/cx18-controls.h b/drivers/media/pci/cx18/cx18-controls.h index cb5dfc7b2054..326794887863 100644 --- a/drivers/media/pci/cx18/cx18-controls.h +++ b/drivers/media/pci/cx18/cx18-controls.h @@ -21,4 +21,4 @@ * 02111-1307 USA */ -extern struct cx2341x_handler_ops cx18_cxhdl_ops; +extern const struct cx2341x_handler_ops cx18_cxhdl_ops; diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h index b15beed2dc14..7e31f2a2e085 100644 --- a/drivers/media/pci/cx18/cx18-driver.h +++ b/drivers/media/pci/cx18/cx18-driver.h @@ -49,7 +49,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-fh.h> #include <media/tuner.h> -#include <media/ir-kbd-i2c.h> +#include <media/i2c/ir-kbd-i2c.h> #include "cx18-mailbox.h" #include "cx18-av-core.h" #include "cx23418.h" diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index 55525af1f482..eeb741c7db1b 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -453,8 +453,8 @@ static int cx18_cropcap(struct file *file, void *fh, if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10; - cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11; + cropcap->pixelaspect.numerator = cx->is_50hz ? 54 : 11; + cropcap->pixelaspect.denominator = cx->is_50hz ? 59 : 10; return 0; } diff --git a/drivers/media/pci/cx18/cx23418.h b/drivers/media/pci/cx18/cx23418.h index 767a8d23e3f2..67ffe65b56a3 100644 --- a/drivers/media/pci/cx18/cx23418.h +++ b/drivers/media/pci/cx18/cx23418.h @@ -22,7 +22,7 @@ #ifndef CX23418_H #define CX23418_H -#include <media/cx2341x.h> +#include <media/drv-intf/cx2341x.h> #define MGR_CMD_MASK 0x40000000 /* The MSB of the command code indicates that this is the completion of a diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig index 2e1b88ccdbf2..3435bbaa3167 100644 --- a/drivers/media/pci/cx23885/Kconfig +++ b/drivers/media/pci/cx23885/Kconfig @@ -10,6 +10,7 @@ config VIDEO_CX23885 select VIDEOBUF2_DMA_SG select VIDEO_CX25840 select VIDEO_CX2341X + select VIDEO_CS3308 select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index 88a3afb66d10..bd333875a1f7 100644 --- a/drivers/media/pci/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -30,7 +30,7 @@ #include <linux/slab.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> -#include <media/cx2341x.h> +#include <media/drv-intf/cx2341x.h> #include "cx23885.h" #include "cx23885-ioctl.h" @@ -1138,7 +1138,7 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder) /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const void *parg, +static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index f384f295676e..310ee769aed4 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -19,7 +19,7 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/delay.h> -#include <media/cx25840.h> +#include <media/drv-intf/cx25840.h> #include <linux/firmware.h> #include <misc/altera.h> @@ -715,6 +715,56 @@ struct cx23885_board cx23885_boards[] = { .portb = CX23885_MPEG_DVB, .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_VIEWCAST_260E] = { + .name = "ViewCast 260e", + .porta = CX23885_ANALOG_VIDEO, + .force_bff = 1, + .input = {{ + .type = CX23885_VMUX_COMPOSITE1, + .vmux = CX25840_VIN6_CH1, + .amux = CX25840_AUDIO7, + }, { + .type = CX23885_VMUX_SVIDEO, + .vmux = CX25840_VIN7_CH3 | + CX25840_VIN5_CH1 | + CX25840_SVIDEO_ON, + .amux = CX25840_AUDIO7, + }, { + .type = CX23885_VMUX_COMPONENT, + .vmux = CX25840_VIN7_CH3 | + CX25840_VIN6_CH2 | + CX25840_VIN5_CH1 | + CX25840_COMPONENT_ON, + .amux = CX25840_AUDIO7, + } }, + }, + [CX23885_BOARD_VIEWCAST_460E] = { + .name = "ViewCast 460e", + .porta = CX23885_ANALOG_VIDEO, + .force_bff = 1, + .input = {{ + .type = CX23885_VMUX_COMPOSITE1, + .vmux = CX25840_VIN4_CH1, + .amux = CX25840_AUDIO7, + }, { + .type = CX23885_VMUX_SVIDEO, + .vmux = CX25840_VIN7_CH3 | + CX25840_VIN6_CH1 | + CX25840_SVIDEO_ON, + .amux = CX25840_AUDIO7, + }, { + .type = CX23885_VMUX_COMPONENT, + .vmux = CX25840_VIN7_CH3 | + CX25840_VIN6_CH1 | + CX25840_VIN5_CH2 | + CX25840_COMPONENT_ON, + .amux = CX25840_AUDIO7, + }, { + .type = CX23885_VMUX_COMPOSITE2, + .vmux = CX25840_VIN6_CH1, + .amux = CX25840_AUDIO7, + } }, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -1002,6 +1052,14 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0xf038, .card = CX23885_BOARD_HAUPPAUGE_HVR5525, + }, { + .subvendor = 0x1576, + .subdevice = 0x0260, + .card = CX23885_BOARD_VIEWCAST_260E, + }, { + .subvendor = 0x1576, + .subdevice = 0x0460, + .card = CX23885_BOARD_VIEWCAST_460E, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -1034,6 +1092,28 @@ void cx23885_card_list(struct cx23885_dev *dev) dev->name, i, cx23885_boards[i].name); } +static void viewcast_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) +{ + u32 sn; + + /* The serial number record begins with tag 0x59 */ + if (*(eeprom_data + 0x00) != 0x59) { + pr_info("%s() eeprom records are undefined, no serial number\n", + __func__); + return; + } + + sn = (*(eeprom_data + 0x06) << 24) | + (*(eeprom_data + 0x05) << 16) | + (*(eeprom_data + 0x04) << 8) | + (*(eeprom_data + 0x03)); + + pr_info("%s: card '%s' sn# MM%d\n", + dev->name, + cx23885_boards[dev->board].name, + sn); +} + static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) { struct tveeprom tv; @@ -1671,6 +1751,12 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx23885_gpio_set(dev, GPIO_8 | GPIO_9); msleep(100); break; + case CX23885_BOARD_VIEWCAST_260E: + case CX23885_BOARD_VIEWCAST_460E: + /* For documentation purposes, it's worth noting that this + * card does not have any GPIO's connected to subcomponents. + */ + break; } } @@ -1917,6 +2003,14 @@ void cx23885_card_setup(struct cx23885_dev *dev) if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; + case CX23885_BOARD_VIEWCAST_260E: + case CX23885_BOARD_VIEWCAST_460E: + dev->i2c_bus[1].i2c_client.addr = 0xa0 >> 1; + tveeprom_read(&dev->i2c_bus[1].i2c_client, + eeprom, sizeof(eeprom)); + if (dev->i2c_bus[0].i2c_rc == 0) + viewcast_eeprom(dev, eeprom); + break; } switch (dev->board) { @@ -2120,6 +2214,8 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_DVBSKY_S950: case CX23885_BOARD_DVBSKY_S952: case CX23885_BOARD_DVBSKY_T982: + case CX23885_BOARD_VIEWCAST_260E: + case CX23885_BOARD_VIEWCAST_460E: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, "cx25840", 0x88 >> 1, NULL); @@ -2130,6 +2226,24 @@ void cx23885_card_setup(struct cx23885_dev *dev) break; } + switch (dev->board) { + case CX23885_BOARD_VIEWCAST_260E: + v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_bus[0].i2c_adap, + "cs3308", 0x82 >> 1, NULL); + break; + case CX23885_BOARD_VIEWCAST_460E: + /* This cs3308 controls the audio from the breakout cable */ + v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_bus[0].i2c_adap, + "cs3308", 0x80 >> 1, NULL); + /* This cs3308 controls the audio from the onboard header */ + v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_bus[0].i2c_adap, + "cs3308", 0x82 >> 1, NULL); + break; + } + /* AUX-PLL 27MHz CLK */ switch (dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index e8f847226a19..813c217b5e1a 100644 --- a/drivers/media/pci/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c @@ -427,7 +427,7 @@ static void cx23885_wakeup(struct cx23885_tsport *port, buf = list_entry(q->active.next, struct cx23885_buffer, queue); - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); buf->vb.sequence = q->count++; dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.vb2_buf.index, @@ -968,6 +968,16 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) call_all(dev, core, s_power, 0); cx23885_ir_init(dev); + if (dev->board == CX23885_BOARD_VIEWCAST_460E) { + /* + * GPIOs 9/8 are input detection bits for the breakout video + * (gpio 8) and audio (gpio 9) cables. When they're attached, + * this gpios are pulled high. Make sure these GPIOs are marked + * as inputs. + */ + cx23885_gpio_enable(dev, 0x300, 0); + } + if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { if (cx23885_video_register(dev) < 0) { printk(KERN_ERR "%s() Failed to register analog " diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index c4307ad8594c..80319bb73d94 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -92,7 +92,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const void *parg, +static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -2168,11 +2168,12 @@ static int dvb_register(struct cx23885_tsport *port) } port->i2c_client_tuner = client_tuner; break; - case CX23885_BOARD_HAUPPAUGE_HVR5525: - switch (port->nr) { + case CX23885_BOARD_HAUPPAUGE_HVR5525: { struct m88rs6000t_config m88rs6000t_config; struct a8293_platform_data a8293_pdata = {}; + switch (port->nr) { + /* port b - satellite */ case 1: /* attach frontend */ @@ -2267,6 +2268,7 @@ static int dvb_register(struct cx23885_tsport *port) break; } break; + } default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", diff --git a/drivers/media/pci/cx23885/cx23885-i2c.c b/drivers/media/pci/cx23885/cx23885-i2c.c index 1135ea3f6ce5..ae061b358591 100644 --- a/drivers/media/pci/cx23885/cx23885-i2c.c +++ b/drivers/media/pci/cx23885/cx23885-i2c.c @@ -279,6 +279,8 @@ static char *i2c_devs[128] = { [0x10 >> 1] = "tda10048", [0x12 >> 1] = "dib7000pc", [0x1c >> 1] = "lgdt3303", + [0x80 >> 1] = "cs3308", + [0x82 >> 1] = "cs3308", [0x86 >> 1] = "tda9887", [0x32 >> 1] = "cx24227", [0x88 >> 1] = "cx25837", diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c index 088799c3b49b..64328d08ac2f 100644 --- a/drivers/media/pci/cx23885/cx23885-input.c +++ b/drivers/media/pci/cx23885/cx23885-input.c @@ -268,7 +268,7 @@ int cx23885_input_init(struct cx23885_dev *dev) struct rc_dev *rc; char *rc_map; enum rc_driver_type driver_type; - unsigned long allowed_protos; + u64 allowed_protos; int ret; diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c index cf3cb1324c55..39750ebcc04c 100644 --- a/drivers/media/pci/cx23885/cx23885-vbi.c +++ b/drivers/media/pci/cx23885/cx23885-vbi.c @@ -83,7 +83,7 @@ int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status) if (status & VID_BC_MSK_VBI_RISCI1) { dprintk(1, "%s() VID_BC_MSK_VBI_RISCI1\n", __func__); spin_lock(&dev->slock); - count = cx_read(VID_A_GPCNT); + count = cx_read(VBI_A_GPCNT); cx23885_video_wakeup(dev, &dev->vbiq, count); spin_unlock(&dev->slock); handled++; @@ -103,7 +103,6 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev, VBI_LINE_LENGTH, buf->risc.dma); /* reset counter */ - cx_write(VID_A_GPCNT_CTL, 3); cx_write(VID_A_VBI_CTRL, 3); cx_write(VBI_A_GPCNT_CTL, 3); q->count = 0; @@ -121,7 +120,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev, /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const void *parg, +static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index 71a80e2b842c..e1d7d0847167 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c @@ -35,7 +35,7 @@ #include "cx23885-ioctl.h" #include "tuner-xc2028.h" -#include <media/cx25840.h> +#include <media/drv-intf/cx25840.h> MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); @@ -105,7 +105,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev, struct cx23885_buffer, queue); buf->vb.sequence = q->count++; - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.vb2_buf.index, count, q->count); list_del(&buf->queue); @@ -114,11 +114,19 @@ void cx23885_video_wakeup(struct cx23885_dev *dev, int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) { + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .format.code = MEDIA_BUS_FMT_FIXED, + }; + dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__, (unsigned int)norm, v4l2_norm_to_name(norm)); + if (dev->tvnorm == norm) + return 0; + if (dev->tvnorm != norm) { if (vb2_is_busy(&dev->vb2_vidq) || vb2_is_busy(&dev->vb2_vbiq) || vb2_is_busy(&dev->vb2_mpegq)) @@ -126,9 +134,17 @@ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) } dev->tvnorm = norm; + dev->width = 720; + dev->height = norm_maxh(norm); + dev->field = V4L2_FIELD_INTERLACED; call_all(dev, video, s_std, norm); + format.format.width = dev->width; + format.format.height = dev->height; + format.format.field = dev->field; + call_all(dev, pad, set_fmt, NULL, &format); + return 0; } @@ -247,7 +263,9 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) || (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) || (dev->board == CX23885_BOARD_MYGICA_X8507) || - (dev->board == CX23885_BOARD_AVERMEDIA_HC81R)) { + (dev->board == CX23885_BOARD_AVERMEDIA_HC81R) || + (dev->board == CX23885_BOARD_VIEWCAST_260E) || + (dev->board == CX23885_BOARD_VIEWCAST_460E)) { /* Configure audio routing */ v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, INPUT(input)->amux, 0, 0); @@ -315,7 +333,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev, return 0; } -static int queue_setup(struct vb2_queue *q, const void *parg, +static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -545,7 +563,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; field = f->fmt.pix.field; - maxw = norm_maxw(dev->tvnorm); + maxw = 720; maxh = norm_maxh(dev->tvnorm); if (V4L2_FIELD_ANY == field) { @@ -648,6 +666,26 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } +static int vidioc_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *cc) +{ + struct cx23885_dev *dev = video_drvdata(file); + bool is_50hz = dev->tvnorm & V4L2_STD_625_50; + + if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + cc->bounds.left = 0; + cc->bounds.top = 0; + cc->bounds.width = 720; + cc->bounds.height = norm_maxh(dev->tvnorm); + cc->defrect = cc->bounds; + cc->pixelaspect.numerator = is_50hz ? 54 : 11; + cc->pixelaspect.denominator = is_50hz ? 59 : 10; + + return 0; +} + static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) { struct cx23885_dev *dev = video_drvdata(file); @@ -1082,6 +1120,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_dqbuf = vb2_ioctl_dqbuf, .vidioc_streamon = vb2_ioctl_streamon, .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_cropcap = vidioc_cropcap, .vidioc_s_std = vidioc_s_std, .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h index c5ba0833f47a..b1a5409408c7 100644 --- a/drivers/media/pci/cx23885/cx23885.h +++ b/drivers/media/pci/cx23885/cx23885.h @@ -30,7 +30,7 @@ #include <media/rc-core.h> #include "cx23885-reg.h" -#include "media/cx2341x.h" +#include "media/drv-intf/cx2341x.h" #include <linux/mutex.h> @@ -101,6 +101,8 @@ #define CX23885_BOARD_DVBSKY_T982 51 #define CX23885_BOARD_HAUPPAUGE_HVR5525 52 #define CX23885_BOARD_HAUPPAUGE_STARBURST 53 +#define CX23885_BOARD_VIEWCAST_260E 54 +#define CX23885_BOARD_VIEWCAST_460E 55 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 @@ -627,11 +629,6 @@ extern int cx23885_risc_databuffer(struct pci_dev *pci, /* ----------------------------------------------------------- */ /* tv norms */ -static inline unsigned int norm_maxw(v4l2_std_id norm) -{ - return (norm & V4L2_STD_525_60) ? 720 : 768; -} - static inline unsigned int norm_maxh(v4l2_std_id norm) { return (norm & V4L2_STD_525_60) ? 480 : 576; diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index 26e3e296d615..c48bba9daf1f 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -130,7 +130,7 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) buf = list_entry(dmaq->active.next, struct cx25821_buffer, queue); - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); buf->vb.sequence = dmaq->count++; list_del(&buf->queue); vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); @@ -141,20 +141,20 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) return handled; } -static int cx25821_queue_setup(struct vb2_queue *q, const void *parg, +static int cx25821_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct cx25821_channel *chan = q->drv_priv; unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3; - if (fmt && fmt->fmt.pix.sizeimage < size) - return -EINVAL; + alloc_ctxs[0] = chan->dev->alloc_ctx; + + if (*num_planes) + return sizes[0] < size ? -EINVAL : 0; *num_planes = 1; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : size; - alloc_ctxs[0] = chan->dev->alloc_ctx; + sizes[0] = size; return 0; } diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index 1b5268f9bb24..e158a1da1d41 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c @@ -40,7 +40,7 @@ #include <sound/control.h> #include <sound/initval.h> #include <sound/tlv.h> -#include <media/wm8775.h> +#include <media/i2c/wm8775.h> #include "cx88.h" #include "cx88-reg.h" diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c index 8b889135be8a..3233d45d1e5b 100644 --- a/drivers/media/pci/cx88/cx88-blackbird.c +++ b/drivers/media/pci/cx88/cx88-blackbird.c @@ -36,7 +36,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/cx2341x.h> +#include <media/drv-intf/cx2341x.h> #include "cx88.h" @@ -637,7 +637,7 @@ static int blackbird_stop_codec(struct cx8802_dev *dev) /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const void *parg, +static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c index 9a43c7826b60..46fe8c1eb9d4 100644 --- a/drivers/media/pci/cx88/cx88-core.c +++ b/drivers/media/pci/cx88/cx88-core.c @@ -518,7 +518,7 @@ void cx88_wakeup(struct cx88_core *core, buf = list_entry(q->active.next, struct cx88_buffer, list); - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); buf->vb.field = core->field; buf->vb.sequence = q->count++; list_del(&buf->list); diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index f04835073844..afb20756d7a5 100644 --- a/drivers/media/pci/cx88/cx88-dvb.c +++ b/drivers/media/pci/cx88/cx88-dvb.c @@ -82,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const void *parg, +static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c index 007a5eee8e5e..ccc646d819f2 100644 --- a/drivers/media/pci/cx88/cx88-vbi.c +++ b/drivers/media/pci/cx88/cx88-vbi.c @@ -107,7 +107,7 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev, /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const void *parg, +static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index aef9acf351f6..5f331df65fb9 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -41,7 +41,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/wm8775.h> +#include <media/i2c/wm8775.h> MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); @@ -429,7 +429,7 @@ static int restart_video_queue(struct cx8800_dev *dev, /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const void *parg, +static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index 2996eb3ea1fc..78f817ee7e41 100644 --- a/drivers/media/pci/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h @@ -30,10 +30,10 @@ #include <media/tuner.h> #include <media/tveeprom.h> #include <media/videobuf2-dma-sg.h> -#include <media/cx2341x.h> +#include <media/drv-intf/cx2341x.h> #include <media/videobuf2-dvb.h> -#include <media/ir-kbd-i2c.h> -#include <media/wm8775.h> +#include <media/i2c/ir-kbd-i2c.h> +#include <media/i2c/wm8775.h> #include "cx88-reg.h" #include "tuner-xc2028.h" diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index 0ac2dd35fe50..fba5b40a869c 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -81,13 +81,13 @@ static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) { struct ddb *dev = i2c->dev; - int stat; + long stat; u32 val; i2c->done = 0; ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND); stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ); - if (stat <= 0) { + if (stat == 0) { printk(KERN_ERR "I2C timeout\n"); { /* MSI debugging*/ u32 istat = ddbreadl(INTERRUPT_STATUS); diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c index 88915fb87e80..5dd504741b12 100644 --- a/drivers/media/pci/dm1105/dm1105.c +++ b/drivers/media/pci/dm1105/dm1105.c @@ -1206,7 +1206,6 @@ static void dm1105_remove(struct pci_dev *pdev) i2c_del_adapter(&dev->i2c_adap); dm1105_hw_exit(dev); - synchronize_irq(pdev->irq); free_irq(pdev->irq, dev); pci_iounmap(pdev, dev->io_mem); pci_release_regions(pdev); diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c index d84abde5ea29..568c0c8fb2dc 100644 --- a/drivers/media/pci/dt3155/dt3155.c +++ b/drivers/media/pci/dt3155/dt3155.c @@ -131,22 +131,21 @@ static int wait_i2c_reg(void __iomem *addr) } static int -dt3155_queue_setup(struct vb2_queue *vq, const void *parg, +dt3155_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct dt3155_priv *pd = vb2_get_drv_priv(vq); unsigned size = pd->width * pd->height; if (vq->num_buffers + *nbuffers < 2) *nbuffers = 2 - vq->num_buffers; - if (fmt && fmt->fmt.pix.sizeimage < size) - return -EINVAL; - *num_planes = 1; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : size; alloc_ctxs[0] = pd->alloc_ctx; + if (*num_planes) + return sizes[0] < size ? -EINVAL : 0; + *num_planes = 1; + sizes[0] = size; return 0; } @@ -271,7 +270,7 @@ static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id) spin_lock(&ipd->lock); if (ipd->curr_buf && !list_empty(&ipd->dmaq)) { - v4l2_get_timestamp(&ipd->curr_buf->timestamp); + ipd->curr_buf->vb2_buf.timestamp = ktime_get_ns(); ipd->curr_buf->sequence = ipd->sequence++; ipd->curr_buf->field = V4L2_FIELD_NONE; vb2_buffer_done(&ipd->curr_buf->vb2_buf, VB2_BUF_STATE_DONE); diff --git a/drivers/media/pci/ivtv/ivtv-cards.c b/drivers/media/pci/ivtv/ivtv-cards.c index 145e4749a69d..410d97bdf541 100644 --- a/drivers/media/pci/ivtv/ivtv-cards.c +++ b/drivers/media/pci/ivtv/ivtv-cards.c @@ -22,12 +22,12 @@ #include "ivtv-cards.h" #include "ivtv-i2c.h" -#include <media/msp3400.h> -#include <media/m52790.h> -#include <media/wm8775.h> -#include <media/cs53l32a.h> -#include <media/cx25840.h> -#include <media/upd64031a.h> +#include <media/drv-intf/msp3400.h> +#include <media/i2c/m52790.h> +#include <media/i2c/wm8775.h> +#include <media/i2c/cs53l32a.h> +#include <media/drv-intf/cx25840.h> +#include <media/i2c/upd64031a.h> #define MSP_TUNER MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \ MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER) diff --git a/drivers/media/pci/ivtv/ivtv-controls.c b/drivers/media/pci/ivtv/ivtv-controls.c index 8a55ccb8f0c9..9666ca01549c 100644 --- a/drivers/media/pci/ivtv/ivtv-controls.c +++ b/drivers/media/pci/ivtv/ivtv-controls.c @@ -96,7 +96,7 @@ static int ivtv_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val) return 0; } -struct cx2341x_handler_ops ivtv_cxhdl_ops = { +const struct cx2341x_handler_ops ivtv_cxhdl_ops = { .s_audio_mode = ivtv_s_audio_mode, .s_audio_sampling_freq = ivtv_s_audio_sampling_freq, .s_video_encoding = ivtv_s_video_encoding, diff --git a/drivers/media/pci/ivtv/ivtv-controls.h b/drivers/media/pci/ivtv/ivtv-controls.h index 3999e6358312..ea397ba837e3 100644 --- a/drivers/media/pci/ivtv/ivtv-controls.h +++ b/drivers/media/pci/ivtv/ivtv-controls.h @@ -21,7 +21,7 @@ #ifndef IVTV_CONTROLS_H #define IVTV_CONTROLS_H -extern struct cx2341x_handler_ops ivtv_cxhdl_ops; +extern const struct cx2341x_handler_ops ivtv_cxhdl_ops; extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops; int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame); diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index c2e60b4f292d..374033a5bdaf 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -57,7 +57,7 @@ #include "ivtv-gpio.h" #include <linux/dma-mapping.h> #include <media/tveeprom.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> #include "tuner-xc2028.h" /* If you have already X v4l cards, then set this to X. This way @@ -826,7 +826,7 @@ static void ivtv_init_struct2(struct ivtv *itv) IVTV_CARD_INPUT_VID_TUNER) break; } - if (i == itv->nof_inputs) + if (i >= itv->nof_inputs) i = 0; itv->active_input = i; itv->audio_input = itv->card->video_inputs[i].audio_index; diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h index ee0ef6e48c7d..6c08dae67a73 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.h +++ b/drivers/media/pci/ivtv/ivtv-driver.h @@ -64,8 +64,8 @@ #include <media/v4l2-device.h> #include <media/v4l2-fh.h> #include <media/tuner.h> -#include <media/cx2341x.h> -#include <media/ir-kbd-i2c.h> +#include <media/drv-intf/cx2341x.h> +#include <media/i2c/ir-kbd-i2c.h> #include <linux/ivtv.h> diff --git a/drivers/media/pci/ivtv/ivtv-fileops.c b/drivers/media/pci/ivtv/ivtv-fileops.c index 605d280d8a5f..c9bd018e53de 100644 --- a/drivers/media/pci/ivtv/ivtv-fileops.c +++ b/drivers/media/pci/ivtv/ivtv-fileops.c @@ -34,7 +34,7 @@ #include "ivtv-cards.h" #include "ivtv-firmware.h" #include <media/v4l2-event.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> /* This function tries to claim the stream for a specific file descriptor. If no one else is using this stream then the stream is claimed and diff --git a/drivers/media/pci/ivtv/ivtv-firmware.c b/drivers/media/pci/ivtv/ivtv-firmware.c index 4b0e758a7bce..5b3095f65dce 100644 --- a/drivers/media/pci/ivtv/ivtv-firmware.c +++ b/drivers/media/pci/ivtv/ivtv-firmware.c @@ -26,7 +26,7 @@ #include "ivtv-ioctl.h" #include "ivtv-cards.h" #include <linux/firmware.h> -#include <media/saa7127.h> +#include <media/i2c/saa7127.h> #define IVTV_MASK_SPU_ENABLE 0xFFFFFFFE #define IVTV_MASK_VPU_ENABLE15 0xFFFFFFF6 diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c index 1a41ba5c7d30..bccbf2d18e30 100644 --- a/drivers/media/pci/ivtv/ivtv-i2c.c +++ b/drivers/media/pci/ivtv/ivtv-i2c.c @@ -63,7 +63,7 @@ #include "ivtv-cards.h" #include "ivtv-gpio.h" #include "ivtv-i2c.h" -#include <media/cx25840.h> +#include <media/drv-intf/cx25840.h> /* i2c implementation for cx23415/6 chip, ivtv project. * Author: Kevin Thayer (nufan_wfk at yahoo.com) diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c index 9a21c17fc376..2dc4b20f3ac0 100644 --- a/drivers/media/pci/ivtv/ivtv-ioctl.c +++ b/drivers/media/pci/ivtv/ivtv-ioctl.c @@ -32,7 +32,7 @@ #include "ivtv-gpio.h" #include "ivtv-controls.h" #include "ivtv-cards.h" -#include <media/saa7127.h> +#include <media/i2c/saa7127.h> #include <media/tveeprom.h> #include <media/v4l2-event.h> #include <linux/dvb/audio.h> @@ -831,11 +831,11 @@ static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropca struct ivtv *itv = id->itv; if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; - cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; + cropcap->pixelaspect.numerator = itv->is_50hz ? 54 : 11; + cropcap->pixelaspect.denominator = itv->is_50hz ? 59 : 10; } else if (cropcap->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; - cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; + cropcap->pixelaspect.numerator = itv->is_out_50hz ? 54 : 11; + cropcap->pixelaspect.denominator = itv->is_out_50hz ? 59 : 10; } else { return -EINVAL; } diff --git a/drivers/media/pci/ivtv/ivtv-routing.c b/drivers/media/pci/ivtv/ivtv-routing.c index 8898c569a1c9..0c168f238904 100644 --- a/drivers/media/pci/ivtv/ivtv-routing.c +++ b/drivers/media/pci/ivtv/ivtv-routing.c @@ -24,10 +24,10 @@ #include "ivtv-gpio.h" #include "ivtv-routing.h" -#include <media/msp3400.h> -#include <media/m52790.h> -#include <media/upd64031a.h> -#include <media/upd64083.h> +#include <media/drv-intf/msp3400.h> +#include <media/i2c/m52790.h> +#include <media/i2c/upd64031a.h> +#include <media/i2c/upd64083.h> /* Selects the audio input and output according to the current settings. */ diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 3fdbd81b5580..81e1a5e26efb 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -277,7 +277,6 @@ static irqreturn_t netup_unidvb_isr(int irq, void *dev_id) } static int netup_unidvb_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], @@ -580,7 +579,7 @@ static void netup_unidvb_dma_worker(struct work_struct *work) dev_dbg(&ndev->pci_dev->dev, "%s(): buffer %p done, size %d\n", __func__, buf, buf->size); - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->size); vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index f720cea80e28..e227b02cc122 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -309,7 +309,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev, core_dbg("buffer_finish %p\n", q->curr); /* finish current buffer */ - v4l2_get_timestamp(&q->curr->vb2.timestamp); + q->curr->vb2.vb2_buf.timestamp = ktime_get_ns(); q->curr->vb2.sequence = q->seq_nr++; vb2_buffer_done(&q->curr->vb2.vb2_buf, state); q->curr = NULL; diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c index 7fb5ee7e20ac..0584a2adbe99 100644 --- a/drivers/media/pci/saa7134/saa7134-ts.c +++ b/drivers/media/pci/saa7134/saa7134-ts.c @@ -116,7 +116,7 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2) } EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare); -int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg, +int saa7134_ts_queue_setup(struct vb2_queue *q, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c index 6271b0eb0265..e76da37c4a8a 100644 --- a/drivers/media/pci/saa7134/saa7134-vbi.c +++ b/drivers/media/pci/saa7134/saa7134-vbi.c @@ -138,7 +138,7 @@ static int buffer_prepare(struct vb2_buffer *vb2) saa7134_buffer_startpage(buf)); } -static int queue_setup(struct vb2_queue *q, const void *parg, +static int queue_setup(struct vb2_queue *q, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 518086c7aed5..a63c1366a64e 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -32,7 +32,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-event.h> -#include <media/saa6588.h> +#include <media/i2c/saa6588.h> /* ------------------------------------------------------------------ */ @@ -904,7 +904,7 @@ static int buffer_prepare(struct vb2_buffer *vb2) saa7134_buffer_startpage(buf)); } -static int queue_setup(struct vb2_queue *q, const void *parg, +static int queue_setup(struct vb2_queue *q, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 6b6d234f5cab..5938bc781999 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -42,7 +42,7 @@ #include <media/v4l2-ctrls.h> #include <media/tuner.h> #include <media/rc-core.h> -#include <media/ir-kbd-i2c.h> +#include <media/i2c/ir-kbd-i2c.h> #include <media/videobuf2-dma-sg.h> #include <sound/core.h> #include <sound/pcm.h> @@ -820,7 +820,7 @@ void saa7134_video_fini(struct saa7134_dev *dev); int saa7134_ts_buffer_init(struct vb2_buffer *vb2); int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2); -int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg, +int saa7134_ts_queue_setup(struct vb2_queue *q, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]); int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count); diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c index 03cbcd2095c6..c889ec9f8a5a 100644 --- a/drivers/media/pci/saa7146/hexium_gemini.c +++ b/drivers/media/pci/saa7146/hexium_gemini.c @@ -25,7 +25,7 @@ #define DEBUG_VARIABLE debug -#include <media/saa7146_vv.h> +#include <media/drv-intf/saa7146_vv.h> #include <linux/module.h> static int debug; diff --git a/drivers/media/pci/saa7146/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c index 15f0d66ff78a..c306a92e8909 100644 --- a/drivers/media/pci/saa7146/hexium_orion.c +++ b/drivers/media/pci/saa7146/hexium_orion.c @@ -25,7 +25,7 @@ #define DEBUG_VARIABLE debug -#include <media/saa7146_vv.h> +#include <media/drv-intf/saa7146_vv.h> #include <linux/module.h> static int debug; diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index 0ca1e07ae783..504d78807639 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -25,10 +25,10 @@ #define DEBUG_VARIABLE debug -#include <media/saa7146_vv.h> +#include <media/drv-intf/saa7146_vv.h> #include <media/tuner.h> #include <media/v4l2-common.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> #include <linux/module.h> #include "tea6415c.h" diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c index 4432fd69b7cb..67a14c41c227 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c @@ -531,8 +531,7 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc, if (!ret) { vbuf->sequence = solo_enc->sequence++; - vbuf->timestamp.tv_sec = vop_sec(vh); - vbuf->timestamp.tv_usec = vop_usec(vh); + vb->timestamp = ktime_get_ns(); /* Check for motion flags */ if (solo_is_motion_on(solo_enc) && enc_buf->motion) { @@ -663,7 +662,6 @@ static int solo_ring_thread(void *data) } static int solo_enc_queue_setup(struct vb2_queue *q, - const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c index f7ce493b1fee..721ff5320de7 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c @@ -225,7 +225,7 @@ finish_buf: vb2_set_plane_payload(vb, 0, solo_vlines(solo_dev) * solo_bytesperline(solo_dev)); vbuf->sequence = solo_dev->sequence++; - v4l2_get_timestamp(&vbuf->timestamp); + vb->timestamp = ktime_get_ns(); } vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); @@ -313,7 +313,7 @@ static void solo_stop_thread(struct solo_dev *solo_dev) solo_dev->kthread = NULL; } -static int solo_queue_setup(struct vb2_queue *q, const void *parg, +static int solo_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 6367b455a7e7..753411cbbc9a 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -265,7 +265,7 @@ static void vip_active_buf_next(struct sta2x11_vip *vip) /* Videobuf2 Operations */ -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -817,7 +817,7 @@ static irqreturn_t vip_irq(int irq, struct sta2x11_vip *vip) /* Disable acquisition */ reg_write(vip, DVP_CTL, reg_read(vip, DVP_CTL) & ~DVP_CTL_ENA); /* Remove the active buffer from the list */ - v4l2_get_timestamp(&vip->active->vb.timestamp); + vip->active->vb.vb2_buf.timestamp = ktime_get_ns(); vip->active->vb.sequence = vip->sequence++; vb2_buffer_done(&vip->active->vb.vb2_buf, VB2_BUF_STATE_DONE); } diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index f89364951ebd..5e18b6796ed9 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -26,7 +26,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at https://linuxtv.org */ @@ -1537,7 +1537,7 @@ static int get_firmware(struct av7110* av7110) printk(KERN_ERR "dvb-ttpci: usually this should be in " "/usr/lib/hotplug/firmware or /lib/firmware\n"); printk(KERN_ERR "dvb-ttpci: and can be downloaded from" - " http://www.linuxtv.org/download/dvb/firmware/\n"); + " https://linuxtv.org/download/dvb/firmware/\n"); } else printk(KERN_ERR "dvb-ttpci: cannot request firmware" " (error %i)\n", ret); @@ -2314,7 +2314,7 @@ static int frontend_init(struct av7110 *av7110) /* Budgetpatch note: * Original hardware design by Roberto Deza: * There is a DVB_Wiki at - * http://www.linuxtv.org/ + * https://linuxtv.org * * New software triggering design by Emard that works on * original Roberto Deza's hardware: diff --git a/drivers/media/pci/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h index 3a55927edb95..3707ccd02732 100644 --- a/drivers/media/pci/ttpci/av7110.h +++ b/drivers/media/pci/ttpci/av7110.h @@ -32,7 +32,7 @@ #include "stv0297.h" #include "l64781.h" -#include <media/saa7146_vv.h> +#include <media/drv-intf/saa7146_vv.h> #define ANALOG_TUNER_VES1820 1 diff --git a/drivers/media/pci/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c index 9ed1ec7d3551..6fc748e22017 100644 --- a/drivers/media/pci/ttpci/av7110_av.c +++ b/drivers/media/pci/ttpci/av7110_av.c @@ -25,7 +25,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at https://linuxtv.org */ #include <linux/types.h> @@ -280,9 +280,11 @@ int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen) } -int av7110_set_volume(struct av7110 *av7110, int volleft, int volright) +int av7110_set_volume(struct av7110 *av7110, unsigned int volleft, + unsigned int volright) { - int err, vol, val, balance = 0; + unsigned int vol, val, balance = 0; + int err; dprintk(2, "av7110:%p, \n", av7110); @@ -1043,6 +1045,9 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len dprintk(2, "av7110:%p, \n", av7110); + if (len == 0) + return 0; + if (!(av7110->playing & RP_VIDEO)) { if (av7110_av_start_play(av7110, RP_VIDEO) < 0) return -EBUSY; diff --git a/drivers/media/pci/ttpci/av7110_av.h b/drivers/media/pci/ttpci/av7110_av.h index 5f02ef85e47d..f52276f47709 100644 --- a/drivers/media/pci/ttpci/av7110_av.h +++ b/drivers/media/pci/ttpci/av7110_av.h @@ -10,7 +10,8 @@ extern int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len); extern int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen); extern int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len); -extern int av7110_set_volume(struct av7110 *av7110, int volleft, int volright); +extern int av7110_set_volume(struct av7110 *av7110, unsigned int volleft, + unsigned int volright); extern int av7110_av_stop(struct av7110 *av7110, int av); extern int av7110_av_start_record(struct av7110 *av7110, int av, struct dvb_demux_feed *dvbdmxfeed); diff --git a/drivers/media/pci/ttpci/av7110_ca.c b/drivers/media/pci/ttpci/av7110_ca.c index a6079b90252a..bc4c65ffd4b9 100644 --- a/drivers/media/pci/ttpci/av7110_ca.c +++ b/drivers/media/pci/ttpci/av7110_ca.c @@ -25,7 +25,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at https://linuxtv.org */ #include <linux/kernel.h> diff --git a/drivers/media/pci/ttpci/av7110_hw.c b/drivers/media/pci/ttpci/av7110_hw.c index 300bd3c94738..0583d56ef5ef 100644 --- a/drivers/media/pci/ttpci/av7110_hw.c +++ b/drivers/media/pci/ttpci/av7110_hw.c @@ -22,7 +22,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at https://linuxtv.org */ /* for debugging ARM communication: */ diff --git a/drivers/media/pci/ttpci/av7110_v4l.c b/drivers/media/pci/ttpci/av7110_v4l.c index 6c4076acb131..479aff02db81 100644 --- a/drivers/media/pci/ttpci/av7110_v4l.c +++ b/drivers/media/pci/ttpci/av7110_v4l.c @@ -22,7 +22,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at https://linuxtv.org */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c index 3e469d4e0c87..6f0d0161970e 100644 --- a/drivers/media/pci/ttpci/budget-av.c +++ b/drivers/media/pci/ttpci/budget-av.c @@ -30,7 +30,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at https://linuxtv.org */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -46,7 +46,7 @@ #include "tda1004x.h" #include "tua6100.h" #include "dvb-pll.h" -#include <media/saa7146_vv.h> +#include <media/drv-intf/saa7146_vv.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/slab.h> diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c index 1feeeff3681b..7b27af4d9658 100644 --- a/drivers/media/pci/ttpci/budget-ci.c +++ b/drivers/media/pci/ttpci/budget-ci.c @@ -26,7 +26,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at https://linuxtv.org */ #include <linux/module.h> diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c index e9674b40007c..6d42dcfd4825 100644 --- a/drivers/media/pci/ttpci/budget-core.c +++ b/drivers/media/pci/ttpci/budget-core.c @@ -31,7 +31,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at https://linuxtv.org */ diff --git a/drivers/media/pci/ttpci/budget-patch.c b/drivers/media/pci/ttpci/budget-patch.c index b5b65962ce8f..591dbdfa2a13 100644 --- a/drivers/media/pci/ttpci/budget-patch.c +++ b/drivers/media/pci/ttpci/budget-patch.c @@ -27,7 +27,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at https://linuxtv.org */ #include "av7110.h" diff --git a/drivers/media/pci/ttpci/budget.c b/drivers/media/pci/ttpci/budget.c index 99972beca262..de54310a2660 100644 --- a/drivers/media/pci/ttpci/budget.c +++ b/drivers/media/pci/ttpci/budget.c @@ -31,7 +31,7 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at https://linuxtv.org */ #include "budget.h" diff --git a/drivers/media/pci/ttpci/budget.h b/drivers/media/pci/ttpci/budget.h index 1ccbe1a49a4b..655eef5236ca 100644 --- a/drivers/media/pci/ttpci/budget.h +++ b/drivers/media/pci/ttpci/budget.h @@ -13,7 +13,7 @@ #include <linux/module.h> #include <linux/mutex.h> -#include <media/saa7146.h> +#include <media/drv-intf/saa7146.h> extern int budget_debug; diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c index 46642ef9151b..07116a87a57b 100644 --- a/drivers/media/pci/tw68/tw68-video.c +++ b/drivers/media/pci/tw68/tw68-video.c @@ -376,28 +376,28 @@ static int tw68_buffer_count(unsigned int size, unsigned int count) /* ------------------------------------------------------------- */ /* vb2 queue operations */ -static int tw68_queue_setup(struct vb2_queue *q, const void *parg, +static int tw68_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct tw68_dev *dev = vb2_get_drv_priv(q); unsigned tot_bufs = q->num_buffers + *num_buffers; + unsigned size = (dev->fmt->depth * dev->width * dev->height) >> 3; - sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3; + if (tot_bufs < 2) + tot_bufs = 2; + tot_bufs = tw68_buffer_count(size, tot_bufs); + *num_buffers = tot_bufs - q->num_buffers; alloc_ctxs[0] = dev->alloc_ctx; /* - * We allow create_bufs, but only if the sizeimage is the same as the + * We allow create_bufs, but only if the sizeimage is >= as the * current sizeimage. The tw68_buffer_count calculation becomes quite * difficult otherwise. */ - if (fmt && fmt->fmt.pix.sizeimage < sizes[0]) - return -EINVAL; + if (*num_planes) + return sizes[0] < size ? -EINVAL : 0; *num_planes = 1; - if (tot_bufs < 2) - tot_bufs = 2; - tot_bufs = tw68_buffer_count(sizes[0], tot_bufs); - *num_buffers = tot_bufs - q->num_buffers; + sizes[0] = size; return 0; } @@ -1016,7 +1016,7 @@ void tw68_irq_video_done(struct tw68_dev *dev, unsigned long status) buf = list_entry(dev->active.next, struct tw68_buf, list); list_del(&buf->list); spin_unlock(&dev->slock); - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); buf->vb.field = dev->field; buf->vb.sequence = dev->seqnr++; vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); diff --git a/drivers/media/pci/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c index 1136d92af642..9d2697f5b455 100644 --- a/drivers/media/pci/zoran/zoran_card.c +++ b/drivers/media/pci/zoran/zoran_card.c @@ -50,7 +50,7 @@ #include <linux/mutex.h> #include <linux/io.h> #include <media/v4l2-common.h> -#include <media/bt819.h> +#include <media/i2c/bt819.h> #include "videocodec.h" #include "zoran.h" diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index ccbc9742cb7a..0c53805dff0e 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -38,7 +38,7 @@ config VIDEO_SH_VOU depends on MEDIA_CAMERA_SUPPORT depends on VIDEO_DEV && I2C && HAS_DMA depends on ARCH_SHMOBILE || COMPILE_TEST - select VIDEOBUF_DMA_CONTIG + select VIDEOBUF2_DMA_CONTIG help Support for the Video Output Unit (VOU) on SuperH SoCs. diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index f0480d687f17..de32e3a3d4d1 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -1281,7 +1281,7 @@ static inline void vpfe_schedule_bottom_field(struct vpfe_device *vpfe) */ static inline void vpfe_process_buffer_complete(struct vpfe_device *vpfe) { - v4l2_get_timestamp(&vpfe->cur_frm->vb.timestamp); + vpfe->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns(); vpfe->cur_frm->vb.field = vpfe->fmt.fmt.pix.field; vpfe->cur_frm->vb.sequence = vpfe->sequence++; vb2_buffer_done(&vpfe->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); @@ -1898,7 +1898,6 @@ static void vpfe_calculate_offsets(struct vpfe_device *vpfe) /* * vpfe_queue_setup - Callback function for buffer setup. * @vq: vb2_queue ptr - * @fmt: v4l2 format * @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. @@ -1908,22 +1907,24 @@ static void vpfe_calculate_offsets(struct vpfe_device *vpfe) * the buffer count and buffer size */ static int vpfe_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct vpfe_device *vpfe = vb2_get_drv_priv(vq); - - if (fmt && fmt->fmt.pix.sizeimage < vpfe->fmt.fmt.pix.sizeimage) - return -EINVAL; + unsigned size = vpfe->fmt.fmt.pix.sizeimage; if (vq->num_buffers + *nbuffers < 3) *nbuffers = 3 - vq->num_buffers; + alloc_ctxs[0] = vpfe->alloc_ctx; + + if (*nplanes) { + if (sizes[0] < size) + return -EINVAL; + size = sizes[0]; + } *nplanes = 1; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : vpfe->fmt.fmt.pix.sizeimage; - alloc_ctxs[0] = vpfe->alloc_ctx; + sizes[0] = size; vpfe_dbg(1, vpfe, "nbuffers=%d, size=%u\n", *nbuffers, sizes[0]); diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index 7764b9c482ef..d0092dae7a57 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c @@ -202,22 +202,20 @@ static void bcap_free_sensor_formats(struct bcap_device *bcap_dev) } static int bcap_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); - if (fmt && fmt->fmt.pix.sizeimage < bcap_dev->fmt.sizeimage) - return -EINVAL; - if (vq->num_buffers + *nbuffers < 2) *nbuffers = 2; + alloc_ctxs[0] = bcap_dev->alloc_ctx; + + if (*nplanes) + return sizes[0] < bcap_dev->fmt.sizeimage ? -EINVAL : 0; *nplanes = 1; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : bcap_dev->fmt.sizeimage; - alloc_ctxs[0] = bcap_dev->alloc_ctx; + sizes[0] = bcap_dev->fmt.sizeimage; return 0; } @@ -406,7 +404,7 @@ static irqreturn_t bcap_isr(int irq, void *dev_id) spin_lock(&bcap_dev->lock); if (!list_empty(&bcap_dev->dma_queue)) { - v4l2_get_timestamp(&vbuf->timestamp); + vb->timestamp = ktime_get_ns(); if (ppi->err) { vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); ppi->err = false; diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 654e964f84a2..7d28899f89ce 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -246,7 +246,7 @@ void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming) /* Drop frames that do not start/end with a SOI/EOI markers */ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG && - !coda_jpeg_check_buffer(ctx, src_buf)) { + !coda_jpeg_check_buffer(ctx, &src_buf->vb2_buf)) { v4l2_err(&ctx->dev->v4l2_dev, "dropping invalid JPEG frame %d\n", ctx->qsequence); @@ -279,7 +279,7 @@ void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming) if (meta) { meta->sequence = src_buf->sequence; meta->timecode = src_buf->timecode; - meta->timestamp = src_buf->timestamp; + meta->timestamp = src_buf->vb2_buf.timestamp; meta->start = start; meta->end = ctx->bitstream_fifo.kfifo.in & ctx->bitstream_fifo.kfifo.mask; @@ -1364,7 +1364,7 @@ static void coda_finish_encode(struct coda_ctx *ctx) dst_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME; } - dst_buf->timestamp = src_buf->timestamp; + dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp; dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; @@ -2040,7 +2040,7 @@ static void coda_finish_decode(struct coda_ctx *ctx) dst_buf->flags |= ctx->frame_types[ctx->display_idx]; meta = &ctx->frame_metas[ctx->display_idx]; dst_buf->timecode = meta->timecode; - dst_buf->timestamp = meta->timestamp; + dst_buf->vb2_buf.timestamp = meta->timestamp; trace_coda_dec_rot_done(ctx, dst_buf, meta); diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 15516a6e3a39..2d782ce94a67 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -28,7 +28,7 @@ #include <linux/slab.h> #include <linux/videodev2.h> #include <linux/of.h> -#include <linux/platform_data/coda.h> +#include <linux/platform_data/media/coda.h> #include <linux/reset.h> #include <media/v4l2-ctrls.h> @@ -131,6 +131,7 @@ static const struct coda_codec coda7_codecs[] = { CODA_CODEC(CODA7_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1280, 720), CODA_CODEC(CODA7_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG, 8192, 8192), CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088), + CODA_CODEC(CODA7_MODE_DECODE_MP2, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_YUV420, 1920, 1088), CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088), CODA_CODEC(CODA7_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_YUV420, 8192, 8192), }; @@ -139,6 +140,7 @@ static const struct coda_codec coda9_codecs[] = { CODA_CODEC(CODA9_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1920, 1088), CODA_CODEC(CODA9_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1920, 1088), CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088), + CODA_CODEC(CODA9_MODE_DECODE_MP2, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_YUV420, 1920, 1088), CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088), }; @@ -187,6 +189,7 @@ static const struct coda_video_device coda_bit_decoder = { .ops = &coda_bit_decode_ops, .src_formats = { V4L2_PIX_FMT_H264, + V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_MPEG4, }, .dst_formats = { @@ -293,7 +296,8 @@ static void coda_get_max_dimensions(struct coda_dev *dev, *max_h = h; } -const struct coda_video_device *to_coda_video_device(struct video_device *vdev) +static const struct coda_video_device *to_coda_video_device(struct video_device + *vdev) { struct coda_dev *dev = video_get_drvdata(vdev); unsigned int i = vdev - dev->vfd; @@ -469,6 +473,7 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, /* fallthrough */ case V4L2_PIX_FMT_H264: case V4L2_PIX_FMT_MPEG4: + case V4L2_PIX_FMT_MPEG2: f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = coda_estimate_sizeimage(ctx, f->fmt.pix.sizeimage, @@ -920,6 +925,7 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, .vidioc_streamon = v4l2_m2m_ioctl_streamon, .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, @@ -1131,7 +1137,7 @@ static void set_default_params(struct coda_ctx *ctx) /* * Queue operations */ -static int coda_queue_setup(struct vb2_queue *vq, const void *parg, +static int coda_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -1250,6 +1256,9 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) struct vb2_v4l2_buffer *buf; int ret = 0; + if (count < 1) + return -EINVAL; + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) { @@ -1262,20 +1271,10 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) ret = -EINVAL; goto err; } - } else { - if (count < 1) { - ret = -EINVAL; - goto err; - } } ctx->streamon_out = 1; } else { - if (count < 1) { - ret = -EINVAL; - goto err; - } - ctx->streamon_cap = 1; } diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c index 96cd42a0baaf..9f899a6cefed 100644 --- a/drivers/media/platform/coda/coda-jpeg.c +++ b/drivers/media/platform/coda/coda-jpeg.c @@ -178,14 +178,28 @@ int coda_jpeg_write_tables(struct coda_ctx *ctx) return 0; } -bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_v4l2_buffer *vb) +bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb) { - void *vaddr = vb2_plane_vaddr(&vb->vb2_buf, 0); - u16 soi = be16_to_cpup((__be16 *)vaddr); - u16 eoi = be16_to_cpup((__be16 *)(vaddr + - vb2_get_plane_payload(&vb->vb2_buf, 0) - 2)); + void *vaddr = vb2_plane_vaddr(vb, 0); + u16 soi, eoi; + int len, i; + + soi = be16_to_cpup((__be16 *)vaddr); + if (soi != SOI_MARKER) + return false; + + len = vb2_get_plane_payload(vb, 0); + vaddr += len - 2; + for (i = 0; i < 32; i++) { + eoi = be16_to_cpup((__be16 *)(vaddr - i)); + if (eoi == EOI_MARKER) { + if (i > 0) + vb2_set_plane_payload(vb, 0, len - i); + return true; + } + } - return soi == SOI_MARKER && eoi == EOI_MARKER; + return false; } /* diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h index 96532b06bd9e..d08e9843e9f2 100644 --- a/drivers/media/platform/coda/coda.h +++ b/drivers/media/platform/coda/coda.h @@ -138,7 +138,7 @@ struct coda_buffer_meta { struct list_head list; u32 sequence; struct v4l2_timecode timecode; - struct timeval timestamp; + u64 timestamp; u32 start; u32 end; }; @@ -289,7 +289,7 @@ void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, int coda_h264_padding(int size, char *p); -bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_v4l2_buffer *vb); +bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb); int coda_jpeg_write_tables(struct coda_ctx *ctx); void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality); diff --git a/drivers/media/platform/davinci/Kconfig b/drivers/media/platform/davinci/Kconfig index 469e9d28cec0..554e710de487 100644 --- a/drivers/media/platform/davinci/Kconfig +++ b/drivers/media/platform/davinci/Kconfig @@ -3,6 +3,7 @@ config VIDEO_DAVINCI_VPIF_DISPLAY depends on VIDEO_V4L2 depends on ARCH_DAVINCI || COMPILE_TEST depends on HAS_DMA + depends on I2C select VIDEOBUF2_DMA_CONTIG select VIDEO_ADV7343 if MEDIA_SUBDRV_AUTOSELECT select VIDEO_THS7303 if MEDIA_SUBDRV_AUTOSELECT @@ -19,6 +20,7 @@ config VIDEO_DAVINCI_VPIF_CAPTURE depends on VIDEO_V4L2 depends on ARCH_DAVINCI || COMPILE_TEST depends on HAS_DMA + depends on I2C select VIDEOBUF2_DMA_CONTIG help Enables Davinci VPIF module used for capture devices. @@ -33,6 +35,7 @@ config VIDEO_DM6446_CCDC depends on VIDEO_V4L2 depends on ARCH_DAVINCI || COMPILE_TEST depends on HAS_DMA + depends on I2C select VIDEOBUF_DMA_CONTIG help Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces @@ -49,6 +52,7 @@ config VIDEO_DM355_CCDC depends on VIDEO_V4L2 depends on ARCH_DAVINCI || COMPILE_TEST depends on HAS_DMA + depends on I2C select VIDEOBUF_DMA_CONTIG help Enables DM355 CCD hw module. DM355 CCDC hw interfaces @@ -64,6 +68,7 @@ config VIDEO_DM365_ISIF tristate "TI DM365 ISIF video capture driver" depends on VIDEO_V4L2 && ARCH_DAVINCI depends on HAS_DMA + depends on I2C select VIDEOBUF_DMA_CONTIG help Enables ISIF hw module. This is the hardware module for @@ -77,6 +82,7 @@ config VIDEO_DAVINCI_VPBE_DISPLAY tristate "TI DaVinci VPBE V4L2-Display driver" depends on VIDEO_V4L2 && ARCH_DAVINCI depends on HAS_DMA + depends on I2C select VIDEOBUF2_DMA_CONTIG help Enables Davinci VPBE module used for display devices. diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 6d91422c4e4c..0abcdfe97a6c 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -74,7 +74,7 @@ static void vpbe_isr_even_field(struct vpbe_display *disp_obj, if (layer->cur_frm == layer->next_frm) return; - v4l2_get_timestamp(&layer->cur_frm->vb.timestamp); + layer->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_buffer_done(&layer->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); /* Make cur_frm pointing to next_frm */ layer->cur_frm = layer->next_frm; @@ -228,28 +228,27 @@ static int vpbe_buffer_prepare(struct vb2_buffer *vb) * This function allocates memory for the buffers */ static int -vpbe_buffer_queue_setup(struct vb2_queue *vq, const void *parg, +vpbe_buffer_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; /* Get the file handle object and layer object */ struct vpbe_layer *layer = vb2_get_drv_priv(vq); struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev; v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_buffer_setup\n"); - if (fmt && fmt->fmt.pix.sizeimage < layer->pix_fmt.sizeimage) - return -EINVAL; - /* Store number of buffers allocated in numbuffer member */ if (vq->num_buffers + *nbuffers < VPBE_DEFAULT_NUM_BUFS) *nbuffers = VPBE_DEFAULT_NUM_BUFS - vq->num_buffers; + alloc_ctxs[0] = layer->alloc_ctx; + + if (*nplanes) + return sizes[0] < layer->pix_fmt.sizeimage ? -EINVAL : 0; *nplanes = 1; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : layer->pix_fmt.sizeimage; - alloc_ctxs[0] = layer->alloc_ctx; + sizes[0] = layer->pix_fmt.sizeimage; return 0; } diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index c1e573b7cc6f..08f7028c7560 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -104,7 +104,6 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb) /** * vpif_buffer_queue_setup : Callback function for buffer setup. * @vq: vb2_queue ptr - * @fmt: v4l2 format * @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. @@ -114,26 +113,26 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb) * the buffer count and buffer size */ static int vpif_buffer_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct channel_obj *ch = vb2_get_drv_priv(vq); - struct common_obj *common; - - common = &ch->common[VPIF_VIDEO_INDEX]; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + unsigned size = common->fmt.fmt.pix.sizeimage; vpif_dbg(2, debug, "vpif_buffer_setup\n"); - if (fmt && fmt->fmt.pix.sizeimage < common->fmt.fmt.pix.sizeimage) - return -EINVAL; + if (*nplanes) { + if (sizes[0] < size) + return -EINVAL; + size = sizes[0]; + } if (vq->num_buffers + *nbuffers < 3) *nbuffers = 3 - vq->num_buffers; *nplanes = 1; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : common->fmt.fmt.pix.sizeimage; + sizes[0] = size; alloc_ctxs[0] = common->alloc_ctx; /* Calculate the offset for Y and C data in the buffer */ @@ -331,7 +330,7 @@ static struct vb2_ops video_qops = { */ static void vpif_process_buffer_complete(struct common_obj *common) { - v4l2_get_timestamp(&common->cur_frm->vb.timestamp); + common->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_buffer_done(&common->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); /* Make curFrm pointing to nextFrm */ common->cur_frm = common->next_frm; diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index fd2780306c17..f40755cf1bf2 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -99,7 +99,6 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb) /** * vpif_buffer_queue_setup : Callback function for buffer setup. * @vq: vb2_queue ptr - * @fmt: v4l2 format * @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. @@ -109,22 +108,24 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb) * the buffer count and buffer size */ static int vpif_buffer_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct channel_obj *ch = vb2_get_drv_priv(vq); struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + unsigned size = common->fmt.fmt.pix.sizeimage; - if (fmt && fmt->fmt.pix.sizeimage < common->fmt.fmt.pix.sizeimage) - return -EINVAL; + if (*nplanes) { + if (sizes[0] < size) + return -EINVAL; + size = sizes[0]; + } if (vq->num_buffers + *nbuffers < 3) *nbuffers = 3 - vq->num_buffers; *nplanes = 1; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : common->fmt.fmt.pix.sizeimage; + sizes[0] = size; alloc_ctxs[0] = common->alloc_ctx; /* Calculate the offset for Y and C data in the buffer */ @@ -330,7 +331,7 @@ static void process_interlaced_mode(int fid, struct common_obj *common) /* one frame is displayed If next frame is * available, release cur_frm and move on */ /* Copy frame display time */ - v4l2_get_timestamp(&common->cur_frm->vb.timestamp); + common->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns(); /* Change status of the cur_frm */ vb2_buffer_done(&common->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); @@ -386,8 +387,8 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) if (!channel_first_int[i][channel_id]) { /* Mark status of the cur_frm to * done and unlock semaphore on it */ - v4l2_get_timestamp( - &common->cur_frm->vb.timestamp); + common->cur_frm->vb.vb2_buf.timestamp = + ktime_get_ns(); vb2_buffer_done(&common->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); /* Make cur_frm pointing to next_frm */ diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index d82e717acba7..93782f15b825 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -86,7 +86,7 @@ void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state) dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); if (src_vb && dst_vb) { - dst_vb->timestamp = src_vb->timestamp; + dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; dst_vb->timecode = src_vb->timecode; dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_vb->flags |= @@ -125,7 +125,7 @@ static int gsc_get_bufs(struct gsc_ctx *ctx) if (ret) return ret; - dst_vb->timestamp = src_vb->timestamp; + dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; return 0; } @@ -212,7 +212,6 @@ put_device: } static int gsc_m2m_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *allocators[]) { diff --git a/drivers/media/platform/exynos4-is/common.c b/drivers/media/platform/exynos4-is/common.c index 0eb34ecb8ee4..b6716c57b5db 100644 --- a/drivers/media/platform/exynos4-is/common.c +++ b/drivers/media/platform/exynos4-is/common.c @@ -10,7 +10,7 @@ */ #include <linux/module.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> #include "common.h" /* Called with the media graph mutex held or entity->stream_count > 0. */ diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 99e57320e6f7..0d549a6c8a13 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -193,7 +193,7 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) test_bit(ST_CAPT_RUN, &fimc->state) && deq_buf) { v_buf = fimc_active_queue_pop(cap); - v4l2_get_timestamp(&v_buf->vb.timestamp); + v_buf->vb.vb2_buf.timestamp = ktime_get_ns(); v_buf->vb.sequence = cap->frame_count++; vb2_buffer_done(&v_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); @@ -338,37 +338,36 @@ int fimc_capture_resume(struct fimc_dev *fimc) } -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *allocators[]) { - const struct v4l2_format *pfmt = parg; - const struct v4l2_pix_format_mplane *pixm = NULL; struct fimc_ctx *ctx = vq->drv_priv; struct fimc_frame *frame = &ctx->d_frame; struct fimc_fmt *fmt = frame->fmt; - unsigned long wh; + unsigned long wh = frame->f_width * frame->f_height; int i; - if (pfmt) { - pixm = &pfmt->fmt.pix_mp; - fmt = fimc_find_format(&pixm->pixelformat, NULL, - FMT_FLAGS_CAM | FMT_FLAGS_M2M, -1); - wh = pixm->width * pixm->height; - } else { - wh = frame->f_width * frame->f_height; - } - if (fmt == NULL) return -EINVAL; + if (*num_planes) { + if (*num_planes != fmt->memplanes) + return -EINVAL; + for (i = 0; i < *num_planes; i++) { + if (sizes[i] < (wh * fmt->depth[i]) / 8) + return -EINVAL; + allocators[i] = ctx->fimc_dev->alloc_ctx; + } + return 0; + } + *num_planes = fmt->memplanes; for (i = 0; i < fmt->memplanes; i++) { unsigned int size = (wh * fmt->depth[i]) / 8; - if (pixm) - sizes[i] = max(size, pixm->plane_fmt[i].sizeimage); - else if (fimc_fmt_is_user_defined(fmt->color)) + + if (fimc_fmt_is_user_defined(fmt->color)) sizes[i] = frame->payload[i]; else sizes[i] = max_t(u32, size, frame->payload[i]); diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h index d336fa2916df..6b7435453d2a 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ b/drivers/media/platform/exynos4-is/fimc-core.h @@ -27,7 +27,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-mem2mem.h> #include <media/v4l2-mediabus.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> #define dbg(fmt, args...) \ pr_debug("%s:%d: " fmt "\n", __func__, __LINE__, ##args) diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index 6e6648446f00..0dd22ec66694 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c @@ -30,7 +30,7 @@ #include <media/v4l2-ioctl.h> #include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> #include "common.h" #include "media-dev.h" @@ -39,39 +39,36 @@ #include "fimc-is-param.h" static int isp_video_capture_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *allocators[]) { - const struct v4l2_format *pfmt = parg; struct fimc_isp *isp = vb2_get_drv_priv(vq); struct v4l2_pix_format_mplane *vid_fmt = &isp->video_capture.pixfmt; - const struct v4l2_pix_format_mplane *pixm = NULL; - const struct fimc_fmt *fmt; + const struct fimc_fmt *fmt = isp->video_capture.format; unsigned int wh, i; - if (pfmt) { - pixm = &pfmt->fmt.pix_mp; - fmt = fimc_isp_find_format(&pixm->pixelformat, NULL, -1); - wh = pixm->width * pixm->height; - } else { - fmt = isp->video_capture.format; - wh = vid_fmt->width * vid_fmt->height; - } + wh = vid_fmt->width * vid_fmt->height; if (fmt == NULL) return -EINVAL; *num_buffers = clamp_t(u32, *num_buffers, FIMC_ISP_REQ_BUFS_MIN, FIMC_ISP_REQ_BUFS_MAX); + if (*num_planes) { + if (*num_planes != fmt->memplanes) + return -EINVAL; + for (i = 0; i < *num_planes; i++) { + if (sizes[i] < (wh * fmt->depth[i]) / 8) + return -EINVAL; + allocators[i] = isp->alloc_ctx; + } + return 0; + } + *num_planes = fmt->memplanes; for (i = 0; i < fmt->memplanes; i++) { - unsigned int size = (wh * fmt->depth[i]) / 8; - if (pixm) - sizes[i] = max(size, pixm->plane_fmt[i].sizeimage); - else - sizes[i] = size; + sizes[i] = (wh * fmt->depth[i]) / 8; allocators[i] = isp->alloc_ctx; } @@ -254,7 +251,7 @@ void fimc_isp_video_irq_handler(struct fimc_is *is) buf_index = (is->i2h_cmd.args[1] - 1) % video->buf_count; vbuf = &video->buffers[buf_index]->vb; - v4l2_get_timestamp(&vbuf->timestamp); + vbuf->vb2_buf.timestamp = ktime_get_ns(); vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); video->buf_mask &= ~BIT(buf_index); diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h index c2d25df85db9..e0686b5f1bf8 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.h +++ b/drivers/media/platform/exynos4-is/fimc-isp.h @@ -24,7 +24,7 @@ #include <media/videobuf2-v4l2.h> #include <media/v4l2-device.h> #include <media/v4l2-mediabus.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> extern int fimc_isp_debug; diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.c b/drivers/media/platform/exynos4-is/fimc-lite-reg.c index 0477716a20db..f0acc550d065 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite-reg.c +++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.c @@ -12,7 +12,7 @@ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/io.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> #include "fimc-lite-reg.h" #include "fimc-lite.h" diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 60660c3a5de0..639ee710499e 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -30,7 +30,7 @@ #include <media/v4l2-mem2mem.h> #include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> #include "common.h" #include "fimc-core.h" @@ -292,7 +292,7 @@ static irqreturn_t flite_irq_handler(int irq, void *priv) test_bit(ST_FLITE_RUN, &fimc->state) && !list_empty(&fimc->active_buf_q)) { vbuf = fimc_lite_active_queue_pop(fimc); - v4l2_get_timestamp(&vbuf->vb.timestamp); + vbuf->vb.vb2_buf.timestamp = ktime_get_ns(); vbuf->vb.sequence = fimc->frame_count++; flite_hw_mask_dma_buffer(fimc, vbuf->index); vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); @@ -355,37 +355,34 @@ static void stop_streaming(struct vb2_queue *q) fimc_lite_stop_capture(fimc, false); } -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *allocators[]) { - const struct v4l2_format *pfmt = parg; - const struct v4l2_pix_format_mplane *pixm = NULL; struct fimc_lite *fimc = vq->drv_priv; struct flite_frame *frame = &fimc->out_frame; const struct fimc_fmt *fmt = frame->fmt; - unsigned long wh; + unsigned long wh = frame->f_width * frame->f_height; int i; - if (pfmt) { - pixm = &pfmt->fmt.pix_mp; - fmt = fimc_lite_find_format(&pixm->pixelformat, NULL, 0, -1); - wh = pixm->width * pixm->height; - } else { - wh = frame->f_width * frame->f_height; - } - if (fmt == NULL) return -EINVAL; + if (*num_planes) { + if (*num_planes != fmt->memplanes) + return -EINVAL; + for (i = 0; i < *num_planes; i++) { + if (sizes[i] < (wh * fmt->depth[i]) / 8) + return -EINVAL; + allocators[i] = fimc->alloc_ctx; + } + return 0; + } + *num_planes = fmt->memplanes; for (i = 0; i < fmt->memplanes; i++) { - unsigned int size = (wh * fmt->depth[i]) / 8; - if (pixm) - sizes[i] = max(size, pixm->plane_fmt[i].sizeimage); - else - sizes[i] = size; + sizes[i] = (wh * fmt->depth[i]) / 8; allocators[i] = fimc->alloc_ctx; } diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h index b302305dedbe..11690d563e06 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.h +++ b/drivers/media/platform/exynos4-is/fimc-lite.h @@ -23,7 +23,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-mediabus.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> #define FIMC_LITE_DRV_NAME "exynos-fimc-lite" #define FLITE_CLK_NAME "flite" diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c index 4d1d64a46b21..5aa857c7b631 100644 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c @@ -132,7 +132,7 @@ static void fimc_device_run(void *priv) if (ret) goto dma_unlock; - dst_vb->timestamp = src_vb->timestamp; + dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_vb->flags |= src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; @@ -176,7 +176,7 @@ static void fimc_job_abort(void *priv) fimc_m2m_shutdown(priv); } -static int fimc_queue_setup(struct vb2_queue *vq, const void *parg, +static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *allocators[]) { diff --git a/drivers/media/platform/exynos4-is/fimc-reg.c b/drivers/media/platform/exynos4-is/fimc-reg.c index df0cbcb69b6b..0806724553a2 100644 --- a/drivers/media/platform/exynos4-is/fimc-reg.c +++ b/drivers/media/platform/exynos4-is/fimc-reg.c @@ -13,7 +13,7 @@ #include <linux/io.h> #include <linux/regmap.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> #include "media-dev.h" #include "fimc-reg.h" diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 4f5586a4cbff..9481ce3201a2 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -31,7 +31,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-of.h> #include <media/media-device.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> #include "media-dev.h" #include "fimc-core.h" diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h index 03214541f149..93a96126929b 100644 --- a/drivers/media/platform/exynos4-is/media-dev.h +++ b/drivers/media/platform/exynos4-is/media-dev.h @@ -19,7 +19,7 @@ #include <media/media-entity.h> #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> #include "fimc-core.h" #include "fimc-lite.h" diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index 4b85105dc159..ff5dabf24694 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -29,7 +29,7 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/videodev2.h> -#include <media/exynos-fimc.h> +#include <media/drv-intf/exynos-fimc.h> #include <media/v4l2-of.h> #include <media/v4l2-subdev.h> diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index 29973f9bf8db..7383818c2be6 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -207,7 +207,7 @@ static void dma_callback(void *data) src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); - dst_vb->timestamp = src_vb->timestamp; + dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_vb->flags |= src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; @@ -798,7 +798,6 @@ struct vb2_dc_conf { }; static int deinterlace_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index aa2b44041d3f..9b878deb1437 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -25,7 +25,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> -#include <media/ov7670.h> +#include <media/i2c/ov7670.h> #include <media/videobuf2-vmalloc.h> #include <media/videobuf2-dma-contig.h> #include <media/videobuf2-dma-sg.h> @@ -226,7 +226,7 @@ static void mcam_buffer_done(struct mcam_camera *cam, int frame, vbuf->vb2_buf.planes[0].bytesused = cam->pix_format.sizeimage; vbuf->sequence = cam->buf_seq[frame]; vbuf->field = V4L2_FIELD_NONE; - v4l2_get_timestamp(&vbuf->timestamp); + vbuf->vb2_buf.timestamp = ktime_get_ns(); vb2_set_plane_payload(&vbuf->vb2_buf, 0, cam->pix_format.sizeimage); vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); } @@ -1049,24 +1049,25 @@ static int mcam_read_setup(struct mcam_camera *cam) */ static int mcam_vb_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbufs, + unsigned int *nbufs, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct mcam_camera *cam = vb2_get_drv_priv(vq); int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2; + unsigned size = cam->pix_format.sizeimage; - if (fmt && fmt->fmt.pix.sizeimage < cam->pix_format.sizeimage) - return -EINVAL; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : cam->pix_format.sizeimage; - *num_planes = 1; /* Someday we have to support planar formats... */ if (*nbufs < minbufs) *nbufs = minbufs; if (cam->buffer_mode == B_DMA_contig) alloc_ctxs[0] = cam->vb_alloc_ctx; else if (cam->buffer_mode == B_DMA_sg) alloc_ctxs[0] = cam->vb_alloc_ctx_sg; + + if (*num_planes) + return sizes[0] < size ? -EINVAL : 0; + sizes[0] = size; + *num_planes = 1; /* Someday we have to support planar formats... */ return 0; } diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index b5f165a68566..816f4b6a7b8e 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -18,7 +18,7 @@ #include <linux/slab.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/mmp-camera.h> +#include <linux/platform_data/media/mmp-camera.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/gpio.h> diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index 03a1b606655d..3c4012d42d69 100644 --- a/drivers/media/platform/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -375,7 +375,7 @@ static irqreturn_t emmaprp_irq(int irq_emma, void *data) src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); - dst_vb->timestamp = src_vb->timestamp; + dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_vb->flags |= @@ -689,7 +689,6 @@ static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = { * Queue operations */ static int emmaprp_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/platform/omap/omap_vout_vrfb.c b/drivers/media/platform/omap/omap_vout_vrfb.c index c6e252760c62..b8638e4e1627 100644 --- a/drivers/media/platform/omap/omap_vout_vrfb.c +++ b/drivers/media/platform/omap/omap_vout_vrfb.c @@ -79,10 +79,12 @@ void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout) int j; for (j = 0; j < VRFB_NUM_BUFS; j++) { - omap_vout_free_buffer(vout->smsshado_virt_addr[j], - vout->smsshado_size); - vout->smsshado_virt_addr[j] = 0; - vout->smsshado_phy_addr[j] = 0; + if (vout->smsshado_virt_addr[j]) { + omap_vout_free_buffer(vout->smsshado_virt_addr[j], + vout->smsshado_size); + vout->smsshado_virt_addr[j] = 0; + vout->smsshado_phy_addr[j] = 0; + } } } diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index f4f591652432..ecadca3e945b 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -320,7 +320,6 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh) */ static int isp_video_queue_setup(struct vb2_queue *queue, - const void *parg, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -467,7 +466,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) list_del(&buf->irqlist); spin_unlock_irqrestore(&video->irqlock, flags); - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); /* Do frame number propagation only if this is the output video node. * Frame number either comes from the CSI receivers or it gets diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c index f8e3e83c52a2..485f5259acb0 100644 --- a/drivers/media/platform/rcar_jpu.c +++ b/drivers/media/platform/rcar_jpu.c @@ -1015,28 +1015,33 @@ error_free: * ============================================================================ */ static int jpu_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct jpu_ctx *ctx = vb2_get_drv_priv(vq); struct jpu_q_data *q_data; unsigned int i; q_data = jpu_get_q_data(ctx, vq->type); - *nplanes = q_data->format.num_planes; + if (*nplanes) { + if (*nplanes != q_data->format.num_planes) + return -EINVAL; - for (i = 0; i < *nplanes; i++) { - unsigned int q_size = q_data->format.plane_fmt[i].sizeimage; - unsigned int f_size = fmt ? - fmt->fmt.pix_mp.plane_fmt[i].sizeimage : 0; + for (i = 0; i < *nplanes; i++) { + unsigned int q_size = q_data->format.plane_fmt[i].sizeimage; - if (fmt && f_size < q_size) - return -EINVAL; + if (sizes[i] < q_size) + return -EINVAL; + alloc_ctxs[i] = ctx->jpu->alloc_ctx; + } + return 0; + } - sizes[i] = fmt ? f_size : q_size; + *nplanes = q_data->format.num_planes; + + for (i = 0; i < *nplanes; i++) { + sizes[i] = q_data->format.plane_fmt[i].sizeimage; alloc_ctxs[i] = ctx->jpu->alloc_ctx; } @@ -1300,17 +1305,17 @@ static int jpu_release(struct file *file) struct jpu *jpu = video_drvdata(file); struct jpu_ctx *ctx = fh_to_ctx(file->private_data); - mutex_lock(&jpu->mutex); - if (--jpu->ref_count == 0) - clk_disable_unprepare(jpu->clk); - mutex_unlock(&jpu->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_lock(&jpu->mutex); + if (--jpu->ref_count == 0) + clk_disable_unprepare(jpu->clk); + mutex_unlock(&jpu->mutex); + return 0; } @@ -1560,12 +1565,9 @@ static irqreturn_t jpu_irq_handler(int irq, void *dev_id) } dst_buf->field = src_buf->field; - dst_buf->timestamp = src_buf->timestamp; + dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp; if (src_buf->flags & V4L2_BUF_FLAG_TIMECODE) dst_buf->timecode = src_buf->timecode; - dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_buf->flags |= src_buf->flags & - V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_buf->flags = src_buf->flags & (V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index 537b858cb94a..ec3abbed87d9 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c @@ -338,7 +338,7 @@ irqreturn_t s3c_camif_irq_handler(int irq, void *priv) if (!WARN_ON(vbuf == NULL)) { /* Dequeue a filled buffer */ - v4l2_get_timestamp(&vbuf->vb.timestamp); + vbuf->vb.vb2_buf.timestamp = ktime_get_ns(); vbuf->vb.sequence = vp->frame_sequence++; vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); @@ -435,39 +435,28 @@ static void stop_streaming(struct vb2_queue *vq) camif_stop_capture(vp); } -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *allocators[]) { - const struct v4l2_format *pfmt = parg; - const struct v4l2_pix_format *pix = NULL; struct camif_vp *vp = vb2_get_drv_priv(vq); struct camif_dev *camif = vp->camif; struct camif_frame *frame = &vp->out_frame; - const struct camif_fmt *fmt; + const struct camif_fmt *fmt = vp->out_fmt; unsigned int size; - if (pfmt) { - pix = &pfmt->fmt.pix; - fmt = s3c_camif_find_format(vp, &pix->pixelformat, -1); - if (fmt == NULL) - return -EINVAL; - size = (pix->width * pix->height * fmt->depth) / 8; - } else { - fmt = vp->out_fmt; - if (fmt == NULL) - return -EINVAL; - size = (frame->f_width * frame->f_height * fmt->depth) / 8; - } - - *num_planes = 1; + if (fmt == NULL) + return -EINVAL; - if (pix) - sizes[0] = max(size, pix->sizeimage); - else - sizes[0] = size; + size = (frame->f_width * frame->f_height * fmt->depth) / 8; allocators[0] = camif->alloc_ctx; + if (*num_planes) + return sizes[0] < size ? -EINVAL : 0; + + *num_planes = 1; + sizes[0] = size; + pr_debug("size: %u\n", sizes[0]); return 0; } diff --git a/drivers/media/platform/s3c-camif/camif-core.h b/drivers/media/platform/s3c-camif/camif-core.h index adaf1969ef63..57cbc3d9725d 100644 --- a/drivers/media/platform/s3c-camif/camif-core.h +++ b/drivers/media/platform/s3c-camif/camif-core.h @@ -26,7 +26,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-mediabus.h> #include <media/videobuf2-v4l2.h> -#include <media/s3c_camif.h> +#include <media/drv-intf/s3c_camif.h> #define S3C_CAMIF_DRIVER_NAME "s3c-camif" #define CAMIF_REQ_BUFS_MIN 3 diff --git a/drivers/media/platform/s3c-camif/camif-regs.h b/drivers/media/platform/s3c-camif/camif-regs.h index af2d472ea1dd..5ad36c1c2a5d 100644 --- a/drivers/media/platform/s3c-camif/camif-regs.h +++ b/drivers/media/platform/s3c-camif/camif-regs.h @@ -13,7 +13,7 @@ #define CAMIF_REGS_H_ #include "camif-core.h" -#include <media/s3c_camif.h> +#include <media/drv-intf/s3c_camif.h> /* * The id argument indicates the processing path: diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index e1936d9d27da..74bd46ca7942 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -101,7 +101,7 @@ static struct g2d_frame *get_frame(struct g2d_ctx *ctx, } } -static int g2d_queue_setup(struct vb2_queue *vq, const void *parg, +static int g2d_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -552,7 +552,7 @@ static irqreturn_t g2d_isr(int irq, void *prv) BUG_ON(dst == NULL); dst->timecode = src->timecode; - dst->timestamp = src->timestamp; + 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; diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 4a608cbe0fdb..c3b13a630edf 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2430,7 +2430,6 @@ static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = { */ static int s5p_jpeg_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -2621,7 +2620,7 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id) } dst_buf->timecode = src_buf->timecode; - dst_buf->timestamp = src_buf->timestamp; + dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp; dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; @@ -2752,7 +2751,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx); dst_buf->timecode = src_buf->timecode; - dst_buf->timestamp = src_buf->timestamp; + dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp; v4l2_m2m_buf_done(src_buf, state); if (curr_ctx->mode == S5P_JPEG_ENCODE) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 3ffe2ecfd5ef..927ab4928779 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -85,6 +85,26 @@ void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx) spin_unlock_irqrestore(&dev->condlock, flags); } +int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev) +{ + unsigned long flags; + int ctx; + + spin_lock_irqsave(&dev->condlock, flags); + ctx = dev->curr_ctx; + do { + ctx = (ctx + 1) % MFC_NUM_CONTEXTS; + if (ctx == dev->curr_ctx) { + if (!test_bit(ctx, &dev->ctx_work_bits)) + ctx = -EAGAIN; + break; + } + } while (!test_bit(ctx, &dev->ctx_work_bits)); + spin_unlock_irqrestore(&dev->condlock, flags); + + return ctx; +} + /* Wake up context wait_queue */ static void wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) @@ -105,6 +125,20 @@ static void wake_up_dev(struct s5p_mfc_dev *dev, unsigned int reason, wake_up(&dev->queue); } +void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq) +{ + struct s5p_mfc_buf *b; + int i; + + while (!list_empty(lh)) { + b = list_entry(lh->next, struct s5p_mfc_buf, list); + for (i = 0; i < b->b->vb2_buf.num_planes; i++) + vb2_set_plane_payload(&b->b->vb2_buf, i, 0); + vb2_buffer_done(&b->b->vb2_buf, VB2_BUF_STATE_ERROR); + list_del(&b->list); + } +} + static void s5p_mfc_watchdog(unsigned long arg) { struct s5p_mfc_dev *dev = (struct s5p_mfc_dev *)arg; @@ -150,10 +184,8 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work) if (!ctx) continue; ctx->state = MFCINST_ERROR; - s5p_mfc_hw_call_void(dev->mfc_ops, cleanup_queue, - &ctx->dst_queue, &ctx->vq_dst); - s5p_mfc_hw_call_void(dev->mfc_ops, cleanup_queue, - &ctx->src_queue, &ctx->vq_src); + s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); + s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); clear_work_bit(ctx); wake_up_ctx(ctx, S5P_MFC_R2H_CMD_ERR_RET, 0); } @@ -233,8 +265,8 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx) == dec_y_addr) { dst_buf->b->timecode = src_buf->b->timecode; - dst_buf->b->timestamp = - src_buf->b->timestamp; + dst_buf->b->vb2_buf.timestamp = + src_buf->b->vb2_buf.timestamp; dst_buf->b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_buf->b->flags |= @@ -327,7 +359,6 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, unsigned int dst_frame_status; unsigned int dec_frame_status; struct s5p_mfc_buf *src_buf; - unsigned long flags; unsigned int res_change; dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) @@ -343,17 +374,16 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, if (res_change == S5P_FIMV_RES_INCREASE || res_change == S5P_FIMV_RES_DECREASE) { ctx->state = MFCINST_RES_CHANGE_INIT; - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); wake_up_ctx(ctx, reason, err); WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); s5p_mfc_clock_off(); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); return; } if (ctx->dpb_flush_flag) ctx->dpb_flush_flag = 0; - spin_lock_irqsave(&dev->irqlock, flags); /* All frames remaining in the buffer have been extracted */ if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_EMPTY) { if (ctx->state == MFCINST_RES_CHANGE_FLUSH) { @@ -413,11 +443,10 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, } } leave_handle_frame: - spin_unlock_irqrestore(&dev->irqlock, flags); if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING) || ctx->dst_queue_cnt < ctx->pb_count) clear_work_bit(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); wake_up_ctx(ctx, reason, err); WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); s5p_mfc_clock_off(); @@ -425,15 +454,13 @@ leave_handle_frame: if (test_bit(0, &dev->enter_suspend)) wake_up_dev(dev, reason, err); else - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } /* Error handling for interrupt */ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) { - unsigned long flags; - mfc_err("Interrupt Error: %08x\n", err); if (ctx != NULL) { @@ -450,13 +477,9 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, clear_work_bit(ctx); ctx->state = MFCINST_ERROR; /* Mark all dst buffers as having an error */ - spin_lock_irqsave(&dev->irqlock, flags); - s5p_mfc_hw_call_void(dev->mfc_ops, cleanup_queue, - &ctx->dst_queue, &ctx->vq_dst); + s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); /* Mark all src buffers as having an error */ - s5p_mfc_hw_call_void(dev->mfc_ops, cleanup_queue, - &ctx->src_queue, &ctx->vq_src); - spin_unlock_irqrestore(&dev->irqlock, flags); + s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); wake_up_ctx(ctx, reason, err); break; default: @@ -467,7 +490,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, } } WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); s5p_mfc_clock_off(); wake_up_dev(dev, reason, err); return; @@ -491,7 +514,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height, dev); - s5p_mfc_hw_call_void(dev->mfc_ops, dec_calc_dpb_size, ctx); + s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx); ctx->pb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count, dev); @@ -518,11 +541,11 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, ctx->head_processed = 1; } } - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); clear_work_bit(ctx); WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); s5p_mfc_clock_off(); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); wake_up_ctx(ctx, reason, err); } @@ -532,12 +555,11 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, { struct s5p_mfc_buf *src_buf; struct s5p_mfc_dev *dev; - unsigned long flags; if (ctx == NULL) return; dev = ctx->dev; - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); ctx->int_type = reason; ctx->int_err = err; ctx->int_cond = 1; @@ -545,7 +567,6 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, if (err == 0) { ctx->state = MFCINST_RUNNING; if (!ctx->dpb_flush_flag && ctx->head_processed) { - spin_lock_irqsave(&dev->irqlock, flags); if (!list_empty(&ctx->src_queue)) { src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); @@ -554,7 +575,6 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, vb2_buffer_done(&src_buf->b->vb2_buf, VB2_BUF_STATE_DONE); } - spin_unlock_irqrestore(&dev->irqlock, flags); } else { ctx->dpb_flush_flag = 0; } @@ -563,7 +583,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, s5p_mfc_clock_off(); wake_up(&ctx->queue); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } else { WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); @@ -582,7 +602,6 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx) ctx->state = MFCINST_FINISHED; - spin_lock(&dev->irqlock); if (!list_empty(&ctx->dst_queue)) { mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); @@ -591,7 +610,6 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx) vb2_set_plane_payload(&mb_entry->b->vb2_buf, 0, 0); vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE); } - spin_unlock(&dev->irqlock); clear_work_bit(ctx); @@ -599,7 +617,7 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx) s5p_mfc_clock_off(); wake_up(&ctx->queue); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } /* Interrupt processing */ @@ -613,6 +631,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) mfc_debug_enter(); /* Reset the timeout watchdog */ atomic_set(&dev->watchdog_cnt, 0); + spin_lock(&dev->irqlock); ctx = dev->ctx[dev->curr_ctx]; /* Get the reason of interrupt and the error code */ reason = s5p_mfc_hw_call(dev->mfc_ops, get_int_reason, dev); @@ -639,15 +658,15 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) if (ctx->state == MFCINST_FINISHING && list_empty(&ctx->ref_queue)) { - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); s5p_mfc_handle_stream_complete(ctx); break; } - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); wake_up_ctx(ctx, reason, err); WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); s5p_mfc_clock_off(); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } else { s5p_mfc_handle_frame(ctx, reason, err); } @@ -677,7 +696,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) case S5P_MFC_R2H_CMD_WAKEUP_RET: if (ctx) clear_work_bit(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); wake_up_dev(dev, reason, err); clear_bit(0, &dev->hw_lock); clear_bit(0, &dev->enter_suspend); @@ -688,7 +707,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) break; case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET: - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); ctx->int_type = reason; ctx->int_err = err; s5p_mfc_handle_stream_complete(ctx); @@ -702,12 +721,13 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) default: mfc_debug(2, "Unknown int reason\n"); - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); } + spin_unlock(&dev->irqlock); mfc_debug_leave(); return IRQ_HANDLED; irq_cleanup_hw: - s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); ctx->int_type = reason; ctx->int_err = err; ctx->int_cond = 1; @@ -716,7 +736,8 @@ irq_cleanup_hw: s5p_mfc_clock_off(); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); + spin_unlock(&dev->irqlock); mfc_debug(2, "Exit via irq_cleanup_hw\n"); return IRQ_HANDLED; } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index d1a3f9b1bc44..9eb2481ec292 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -308,7 +308,7 @@ struct s5p_mfc_dev { struct s5p_mfc_pm pm; struct s5p_mfc_variant *variant; int num_inst; - spinlock_t irqlock; /* lock when operating on videobuf2 queues */ + spinlock_t irqlock; /* lock when operating on context */ spinlock_t condlock; /* lock when changing/checking if a context is ready to be processed */ struct mutex mfc_mutex; /* video_device lock */ @@ -653,7 +653,7 @@ struct s5p_mfc_ctx { unsigned int bits; } slice_size; - struct s5p_mfc_codec_ops *c_ops; + const struct s5p_mfc_codec_ops *c_ops; struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS]; struct v4l2_ctrl_handler ctrl_handler; @@ -694,13 +694,7 @@ struct mfc_control { /* Macro for making hardware specific calls */ #define s5p_mfc_hw_call(f, op, args...) \ - ((f && f->op) ? f->op(args) : -ENODEV) - -#define s5p_mfc_hw_call_void(f, op, args...) \ -do { \ - if (f && f->op) \ - f->op(args); \ -} while (0) + ((f && f->op) ? f->op(args) : (typeof(f->op(args)))(-ENODEV)) #define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh) #define ctrl_to_ctx(__ctrl) \ @@ -710,6 +704,8 @@ void clear_work_bit(struct s5p_mfc_ctx *ctx); void set_work_bit(struct s5p_mfc_ctx *ctx); void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx); void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx); +int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev); +void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq); #define HAS_PORTNUM(dev) (dev ? (dev->variant ? \ (dev->variant->port_num ? 1 : 0) : 0) : 0) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 40d8a03a141d..cc888713b3b6 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -319,7 +319,7 @@ void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev) s5p_mfc_clock_on(); s5p_mfc_reset(dev); - s5p_mfc_hw_call_void(dev->mfc_ops, release_dev_context_buffer, dev); + s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev); s5p_mfc_clock_off(); } @@ -468,7 +468,7 @@ int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) } set_work_bit_irqsave(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); if (s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) { /* Error or timeout */ @@ -482,9 +482,9 @@ int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) err_free_desc_buf: if (ctx->type == MFCINST_DECODER) - s5p_mfc_hw_call_void(dev->mfc_ops, release_dec_desc_buffer, ctx); + s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx); err_free_inst_buf: - s5p_mfc_hw_call_void(dev->mfc_ops, release_instance_buffer, ctx); + s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); err: return ret; } @@ -493,17 +493,17 @@ void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) { ctx->state = MFCINST_RETURN_INST; set_work_bit_irqsave(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); /* Wait until instance is returned or timeout occurred */ if (s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) mfc_err("Err returning instance\n"); /* Free resources */ - s5p_mfc_hw_call_void(dev->mfc_ops, release_codec_buffers, ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, release_instance_buffer, ctx); + s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); + s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); if (ctx->type == MFCINST_DECODER) - s5p_mfc_hw_call_void(dev->mfc_ops, release_dec_desc_buffer, ctx); + s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx); ctx->inst_no = MFC_NO_INSTANCE_SET; ctx->state = MFCINST_FREE; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 8c5060a7534f..f2d6376ce618 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -252,7 +252,7 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) return 0; } -static struct s5p_mfc_codec_ops decoder_codec_ops = { +static const struct s5p_mfc_codec_ops decoder_codec_ops = { .pre_seq_start = NULL, .post_seq_start = NULL, .pre_frame_start = NULL, @@ -523,7 +523,7 @@ static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); if (ret) goto out; - s5p_mfc_hw_call_void(dev->mfc_ops, release_codec_buffers, ctx); + s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); ctx->dst_bufs_cnt = 0; } else if (ctx->capture_state == QUEUE_FREE) { WARN_ON(ctx->dst_bufs_cnt != 0); @@ -551,7 +551,7 @@ static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); } else { @@ -831,7 +831,7 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); spin_unlock_irqrestore(&dev->irqlock, flags); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } else { mfc_err("EOS: marking last buffer of stream"); buf = list_entry(ctx->src_queue.prev, @@ -888,7 +888,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = { }; static int s5p_mfc_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *buf_count, + unsigned int *buf_count, unsigned int *plane_count, unsigned int psize[], void *allocators[]) { @@ -1012,7 +1012,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) /* If context is ready then dev = work->data;schedule it to run */ if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); return 0; } @@ -1023,42 +1023,41 @@ static void s5p_mfc_stop_streaming(struct vb2_queue *q) struct s5p_mfc_dev *dev = ctx->dev; int aborted = 0; + spin_lock_irqsave(&dev->irqlock, flags); if ((ctx->state == MFCINST_FINISHING || ctx->state == MFCINST_RUNNING) && dev->curr_ctx == ctx->num && dev->hw_lock) { ctx->state = MFCINST_ABORT; + spin_unlock_irqrestore(&dev->irqlock, flags); s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0); aborted = 1; + spin_lock_irqsave(&dev->irqlock, flags); } if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - spin_lock_irqsave(&dev->irqlock, flags); - s5p_mfc_hw_call_void(dev->mfc_ops, cleanup_queue, - &ctx->dst_queue, &ctx->vq_dst); + s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); INIT_LIST_HEAD(&ctx->dst_queue); ctx->dst_queue_cnt = 0; ctx->dpb_flush_flag = 1; ctx->dec_dst_flag = 0; - spin_unlock_irqrestore(&dev->irqlock, flags); if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) { ctx->state = MFCINST_FLUSH; set_work_bit_irqsave(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); + spin_unlock_irqrestore(&dev->irqlock, flags); if (s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0)) mfc_err("Err flushing buffers\n"); + spin_lock_irqsave(&dev->irqlock, flags); } - } - if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - spin_lock_irqsave(&dev->irqlock, flags); - s5p_mfc_hw_call_void(dev->mfc_ops, cleanup_queue, - &ctx->src_queue, &ctx->vq_src); + } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); INIT_LIST_HEAD(&ctx->src_queue); ctx->src_queue_cnt = 0; - spin_unlock_irqrestore(&dev->irqlock, flags); } if (aborted) ctx->state = MFCINST_RUNNING; + spin_unlock_irqrestore(&dev->irqlock, flags); } @@ -1091,7 +1090,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) } if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } static struct vb2_ops s5p_mfc_dec_qops = { @@ -1104,7 +1103,7 @@ static struct vb2_ops s5p_mfc_dec_qops = { .buf_queue = s5p_mfc_buf_queue, }; -struct s5p_mfc_codec_ops *get_dec_codec_ops(void) +const struct s5p_mfc_codec_ops *get_dec_codec_ops(void) { return &decoder_codec_ops; } @@ -1119,7 +1118,7 @@ const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void) return &s5p_mfc_dec_ioctl_ops; } -#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2CLASS(x) == V4L2_CTRL_CLASS_MPEG) \ +#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_MPEG) \ && V4L2_CTRL_DRIVER_PRIV(x)) int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h index d06a7cab5eb1..886628b153f0 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h @@ -13,7 +13,7 @@ #ifndef S5P_MFC_DEC_H_ #define S5P_MFC_DEC_H_ -struct s5p_mfc_codec_ops *get_dec_codec_ops(void); +const struct s5p_mfc_codec_ops *get_dec_codec_ops(void); struct vb2_ops *get_dec_queue_ops(void); const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void); struct s5p_mfc_fmt *get_dec_def_fmt(bool src); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 5c678ec9c9f2..0434f02a7175 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -769,15 +769,12 @@ static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx) struct s5p_mfc_buf *dst_mb; unsigned long dst_addr; unsigned int dst_size; - unsigned long flags; - spin_lock_irqsave(&dev->irqlock, flags); dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0); dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0); - s5p_mfc_hw_call_void(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr, + s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr, dst_size); - spin_unlock_irqrestore(&dev->irqlock, flags); return 0; } @@ -786,11 +783,9 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_enc_params *p = &ctx->enc_params; struct s5p_mfc_buf *dst_mb; - unsigned long flags; unsigned int enc_pb_count; if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) { - spin_lock_irqsave(&dev->irqlock, flags); if (!list_empty(&ctx->dst_queue)) { dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); @@ -802,14 +797,13 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) vb2_buffer_done(&dst_mb->b->vb2_buf, VB2_BUF_STATE_DONE); } - spin_unlock_irqrestore(&dev->irqlock, flags); } if (!IS_MFCV6_PLUS(dev)) { ctx->state = MFCINST_RUNNING; if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } else { enc_pb_count = s5p_mfc_hw_call(dev->mfc_ops, get_enc_dpb_count, dev); @@ -826,25 +820,20 @@ static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx) struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *dst_mb; struct s5p_mfc_buf *src_mb; - unsigned long flags; unsigned long src_y_addr, src_c_addr, dst_addr; unsigned int dst_size; - spin_lock_irqsave(&dev->irqlock, flags); src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); src_y_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 0); src_c_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 1); - s5p_mfc_hw_call_void(dev->mfc_ops, set_enc_frame_buffer, ctx, + s5p_mfc_hw_call(dev->mfc_ops, set_enc_frame_buffer, ctx, src_y_addr, src_c_addr); - spin_unlock_irqrestore(&dev->irqlock, flags); - spin_lock_irqsave(&dev->irqlock, flags); dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0); dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0); - s5p_mfc_hw_call_void(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr, + s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr, dst_size); - spin_unlock_irqrestore(&dev->irqlock, flags); return 0; } @@ -857,7 +846,6 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) unsigned long mb_y_addr, mb_c_addr; int slice_type; unsigned int strm_size; - unsigned long flags; slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev); strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev); @@ -865,9 +853,8 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) mfc_debug(2, "Encoded stream size: %d\n", strm_size); mfc_debug(2, "Display order: %d\n", mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT)); - spin_lock_irqsave(&dev->irqlock, flags); if (slice_type >= 0) { - s5p_mfc_hw_call_void(dev->mfc_ops, get_enc_frame_buffer, ctx, + s5p_mfc_hw_call(dev->mfc_ops, get_enc_frame_buffer, ctx, &enc_y_addr, &enc_c_addr); list_for_each_entry(mb_entry, &ctx->src_queue, list) { mb_y_addr = vb2_dma_contig_plane_dma_addr( @@ -929,14 +916,13 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) vb2_set_plane_payload(&mb_entry->b->vb2_buf, 0, strm_size); vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE); } - spin_unlock_irqrestore(&dev->irqlock, flags); if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0)) clear_work_bit(ctx); return 0; } -static struct s5p_mfc_codec_ops encoder_codec_ops = { +static const struct s5p_mfc_codec_ops encoder_codec_ops = { .pre_seq_start = enc_pre_seq_start, .post_seq_start = enc_post_seq_start, .pre_frame_start = enc_pre_frame_start, @@ -1120,7 +1106,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) pix_fmt_mp->width, pix_fmt_mp->height, ctx->img_width, ctx->img_height); - s5p_mfc_hw_call_void(dev->mfc_ops, enc_calc_src_size, ctx); + s5p_mfc_hw_call(dev->mfc_ops, enc_calc_src_size, ctx); pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size; pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width; pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size; @@ -1178,7 +1164,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, if (reqbufs->count == 0) { mfc_debug(2, "Freeing buffers\n"); ret = vb2_reqbufs(&ctx->vq_src, reqbufs); - s5p_mfc_hw_call_void(dev->mfc_ops, release_codec_buffers, + s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); ctx->output_state = QUEUE_FREE; return ret; @@ -1741,7 +1727,7 @@ static int vidioc_encoder_cmd(struct file *file, void *priv, if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); spin_unlock_irqrestore(&dev->irqlock, flags); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } else { mfc_debug(2, "EOS: marking last buffer of stream\n"); buf = list_entry(ctx->src_queue.prev, @@ -1818,7 +1804,6 @@ static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb) } static int s5p_mfc_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *buf_count, unsigned int *plane_count, unsigned int psize[], void *allocators[]) { @@ -1969,7 +1954,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) /* If context is ready then dev = work->data;schedule it to run */ if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); return 0; } @@ -1990,15 +1975,13 @@ static void s5p_mfc_stop_streaming(struct vb2_queue *q) ctx->state = MFCINST_FINISHED; spin_lock_irqsave(&dev->irqlock, flags); if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - s5p_mfc_hw_call_void(dev->mfc_ops, cleanup_queue, - &ctx->dst_queue, &ctx->vq_dst); + s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); INIT_LIST_HEAD(&ctx->dst_queue); ctx->dst_queue_cnt = 0; } if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { cleanup_ref_queue(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, cleanup_queue, &ctx->src_queue, - &ctx->vq_src); + s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); INIT_LIST_HEAD(&ctx->src_queue); ctx->src_queue_cnt = 0; } @@ -2038,7 +2021,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) } if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); - s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); } static struct vb2_ops s5p_mfc_enc_qops = { @@ -2052,7 +2035,7 @@ static struct vb2_ops s5p_mfc_enc_qops = { .buf_queue = s5p_mfc_buf_queue, }; -struct s5p_mfc_codec_ops *get_enc_codec_ops(void) +const struct s5p_mfc_codec_ops *get_enc_codec_ops(void) { return &encoder_codec_ops; } @@ -2067,7 +2050,7 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void) return &s5p_mfc_enc_ioctl_ops; } -#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2CLASS(x) == V4L2_CTRL_CLASS_MPEG) \ +#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_MPEG) \ && V4L2_CTRL_DRIVER_PRIV(x)) int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h index 5118d46b3a9e..d0d42f818832 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h @@ -13,7 +13,7 @@ #ifndef S5P_MFC_ENC_H_ #define S5P_MFC_ENC_H_ -struct s5p_mfc_codec_ops *get_enc_codec_ops(void); +const struct s5p_mfc_codec_ops *get_enc_codec_ops(void); struct vb2_ops *get_enc_queue_ops(void); const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void); struct s5p_mfc_fmt *get_enc_def_fmt(bool src); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h index 77a08b19b46d..b6ac417ab63e 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h @@ -20,254 +20,254 @@ struct s5p_mfc_regs { /* codec common registers */ - volatile void __iomem *risc_on; - volatile void __iomem *risc2host_int; - volatile void __iomem *host2risc_int; - volatile void __iomem *risc_base_address; - volatile void __iomem *mfc_reset; - volatile void __iomem *host2risc_command; - volatile void __iomem *risc2host_command; - volatile void __iomem *mfc_bus_reset_ctrl; - volatile void __iomem *firmware_version; - volatile void __iomem *instance_id; - volatile void __iomem *codec_type; - volatile void __iomem *context_mem_addr; - volatile void __iomem *context_mem_size; - volatile void __iomem *pixel_format; - volatile void __iomem *metadata_enable; - volatile void __iomem *mfc_version; - volatile void __iomem *dbg_info_enable; - volatile void __iomem *dbg_buffer_addr; - volatile void __iomem *dbg_buffer_size; - volatile void __iomem *hed_control; - volatile void __iomem *mfc_timeout_value; - volatile void __iomem *hed_shared_mem_addr; - volatile void __iomem *dis_shared_mem_addr;/* only v7 */ - volatile void __iomem *ret_instance_id; - volatile void __iomem *error_code; - volatile void __iomem *dbg_buffer_output_size; - volatile void __iomem *metadata_status; - volatile void __iomem *metadata_addr_mb_info; - volatile void __iomem *metadata_size_mb_info; - volatile void __iomem *dbg_info_stage_counter; + void __iomem *risc_on; + void __iomem *risc2host_int; + void __iomem *host2risc_int; + void __iomem *risc_base_address; + void __iomem *mfc_reset; + void __iomem *host2risc_command; + void __iomem *risc2host_command; + void __iomem *mfc_bus_reset_ctrl; + void __iomem *firmware_version; + void __iomem *instance_id; + void __iomem *codec_type; + void __iomem *context_mem_addr; + void __iomem *context_mem_size; + void __iomem *pixel_format; + void __iomem *metadata_enable; + void __iomem *mfc_version; + void __iomem *dbg_info_enable; + void __iomem *dbg_buffer_addr; + void __iomem *dbg_buffer_size; + void __iomem *hed_control; + void __iomem *mfc_timeout_value; + void __iomem *hed_shared_mem_addr; + void __iomem *dis_shared_mem_addr;/* only v7 */ + void __iomem *ret_instance_id; + void __iomem *error_code; + void __iomem *dbg_buffer_output_size; + void __iomem *metadata_status; + void __iomem *metadata_addr_mb_info; + void __iomem *metadata_size_mb_info; + void __iomem *dbg_info_stage_counter; /* decoder registers */ - volatile void __iomem *d_crc_ctrl; - volatile void __iomem *d_dec_options; - volatile void __iomem *d_display_delay; - volatile void __iomem *d_set_frame_width; - volatile void __iomem *d_set_frame_height; - volatile void __iomem *d_sei_enable; - volatile void __iomem *d_min_num_dpb; - volatile void __iomem *d_min_first_plane_dpb_size; - volatile void __iomem *d_min_second_plane_dpb_size; - volatile void __iomem *d_min_third_plane_dpb_size;/* only v8 */ - volatile void __iomem *d_min_num_mv; - volatile void __iomem *d_mvc_num_views; - volatile void __iomem *d_min_num_dis;/* only v7 */ - volatile void __iomem *d_min_first_dis_size;/* only v7 */ - volatile void __iomem *d_min_second_dis_size;/* only v7 */ - volatile void __iomem *d_min_third_dis_size;/* only v7 */ - volatile void __iomem *d_post_filter_luma_dpb0;/* v7 and v8 */ - volatile void __iomem *d_post_filter_luma_dpb1;/* v7 and v8 */ - volatile void __iomem *d_post_filter_luma_dpb2;/* only v7 */ - volatile void __iomem *d_post_filter_chroma_dpb0;/* v7 and v8 */ - volatile void __iomem *d_post_filter_chroma_dpb1;/* v7 and v8 */ - volatile void __iomem *d_post_filter_chroma_dpb2;/* only v7 */ - volatile void __iomem *d_num_dpb; - volatile void __iomem *d_num_mv; - volatile void __iomem *d_init_buffer_options; - volatile void __iomem *d_first_plane_dpb_stride_size;/* only v8 */ - volatile void __iomem *d_second_plane_dpb_stride_size;/* only v8 */ - volatile void __iomem *d_third_plane_dpb_stride_size;/* only v8 */ - volatile void __iomem *d_first_plane_dpb_size; - volatile void __iomem *d_second_plane_dpb_size; - volatile void __iomem *d_third_plane_dpb_size;/* only v8 */ - volatile void __iomem *d_mv_buffer_size; - volatile void __iomem *d_first_plane_dpb; - volatile void __iomem *d_second_plane_dpb; - volatile void __iomem *d_third_plane_dpb; - volatile void __iomem *d_mv_buffer; - volatile void __iomem *d_scratch_buffer_addr; - volatile void __iomem *d_scratch_buffer_size; - volatile void __iomem *d_metadata_buffer_addr; - volatile void __iomem *d_metadata_buffer_size; - volatile void __iomem *d_nal_start_options;/* v7 and v8 */ - volatile void __iomem *d_cpb_buffer_addr; - volatile void __iomem *d_cpb_buffer_size; - volatile void __iomem *d_available_dpb_flag_upper; - volatile void __iomem *d_available_dpb_flag_lower; - volatile void __iomem *d_cpb_buffer_offset; - volatile void __iomem *d_slice_if_enable; - volatile void __iomem *d_picture_tag; - volatile void __iomem *d_stream_data_size; - volatile void __iomem *d_dynamic_dpb_flag_upper;/* v7 and v8 */ - volatile void __iomem *d_dynamic_dpb_flag_lower;/* v7 and v8 */ - volatile void __iomem *d_display_frame_width; - volatile void __iomem *d_display_frame_height; - volatile void __iomem *d_display_status; - volatile void __iomem *d_display_first_plane_addr; - volatile void __iomem *d_display_second_plane_addr; - volatile void __iomem *d_display_third_plane_addr;/* only v8 */ - volatile void __iomem *d_display_frame_type; - volatile void __iomem *d_display_crop_info1; - volatile void __iomem *d_display_crop_info2; - volatile void __iomem *d_display_picture_profile; - volatile void __iomem *d_display_luma_crc;/* v7 and v8 */ - volatile void __iomem *d_display_chroma0_crc;/* v7 and v8 */ - volatile void __iomem *d_display_chroma1_crc;/* only v8 */ - volatile void __iomem *d_display_luma_crc_top;/* only v6 */ - volatile void __iomem *d_display_chroma_crc_top;/* only v6 */ - volatile void __iomem *d_display_luma_crc_bot;/* only v6 */ - volatile void __iomem *d_display_chroma_crc_bot;/* only v6 */ - volatile void __iomem *d_display_aspect_ratio; - volatile void __iomem *d_display_extended_ar; - volatile void __iomem *d_decoded_frame_width; - volatile void __iomem *d_decoded_frame_height; - volatile void __iomem *d_decoded_status; - volatile void __iomem *d_decoded_first_plane_addr; - volatile void __iomem *d_decoded_second_plane_addr; - volatile void __iomem *d_decoded_third_plane_addr;/* only v8 */ - volatile void __iomem *d_decoded_frame_type; - volatile void __iomem *d_decoded_crop_info1; - volatile void __iomem *d_decoded_crop_info2; - volatile void __iomem *d_decoded_picture_profile; - volatile void __iomem *d_decoded_nal_size; - volatile void __iomem *d_decoded_luma_crc; - volatile void __iomem *d_decoded_chroma0_crc; - volatile void __iomem *d_decoded_chroma1_crc;/* only v8 */ - volatile void __iomem *d_ret_picture_tag_top; - volatile void __iomem *d_ret_picture_tag_bot; - volatile void __iomem *d_ret_picture_time_top; - volatile void __iomem *d_ret_picture_time_bot; - volatile void __iomem *d_chroma_format; - volatile void __iomem *d_vc1_info;/* v7 and v8 */ - volatile void __iomem *d_mpeg4_info; - volatile void __iomem *d_h264_info; - volatile void __iomem *d_metadata_addr_concealed_mb; - volatile void __iomem *d_metadata_size_concealed_mb; - volatile void __iomem *d_metadata_addr_vc1_param; - volatile void __iomem *d_metadata_size_vc1_param; - volatile void __iomem *d_metadata_addr_sei_nal; - volatile void __iomem *d_metadata_size_sei_nal; - volatile void __iomem *d_metadata_addr_vui; - volatile void __iomem *d_metadata_size_vui; - volatile void __iomem *d_metadata_addr_mvcvui;/* v7 and v8 */ - volatile void __iomem *d_metadata_size_mvcvui;/* v7 and v8 */ - volatile void __iomem *d_mvc_view_id; - volatile void __iomem *d_frame_pack_sei_avail; - volatile void __iomem *d_frame_pack_arrgment_id; - volatile void __iomem *d_frame_pack_sei_info; - volatile void __iomem *d_frame_pack_grid_pos; - volatile void __iomem *d_display_recovery_sei_info;/* v7 and v8 */ - volatile void __iomem *d_decoded_recovery_sei_info;/* v7 and v8 */ - volatile void __iomem *d_display_first_addr;/* only v7 */ - volatile void __iomem *d_display_second_addr;/* only v7 */ - volatile void __iomem *d_display_third_addr;/* only v7 */ - volatile void __iomem *d_decoded_first_addr;/* only v7 */ - volatile void __iomem *d_decoded_second_addr;/* only v7 */ - volatile void __iomem *d_decoded_third_addr;/* only v7 */ - volatile void __iomem *d_used_dpb_flag_upper;/* v7 and v8 */ - volatile void __iomem *d_used_dpb_flag_lower;/* v7 and v8 */ + void __iomem *d_crc_ctrl; + void __iomem *d_dec_options; + void __iomem *d_display_delay; + void __iomem *d_set_frame_width; + void __iomem *d_set_frame_height; + void __iomem *d_sei_enable; + void __iomem *d_min_num_dpb; + void __iomem *d_min_first_plane_dpb_size; + void __iomem *d_min_second_plane_dpb_size; + void __iomem *d_min_third_plane_dpb_size;/* only v8 */ + void __iomem *d_min_num_mv; + void __iomem *d_mvc_num_views; + void __iomem *d_min_num_dis;/* only v7 */ + void __iomem *d_min_first_dis_size;/* only v7 */ + void __iomem *d_min_second_dis_size;/* only v7 */ + void __iomem *d_min_third_dis_size;/* only v7 */ + void __iomem *d_post_filter_luma_dpb0;/* v7 and v8 */ + void __iomem *d_post_filter_luma_dpb1;/* v7 and v8 */ + void __iomem *d_post_filter_luma_dpb2;/* only v7 */ + void __iomem *d_post_filter_chroma_dpb0;/* v7 and v8 */ + void __iomem *d_post_filter_chroma_dpb1;/* v7 and v8 */ + void __iomem *d_post_filter_chroma_dpb2;/* only v7 */ + void __iomem *d_num_dpb; + void __iomem *d_num_mv; + void __iomem *d_init_buffer_options; + void __iomem *d_first_plane_dpb_stride_size;/* only v8 */ + void __iomem *d_second_plane_dpb_stride_size;/* only v8 */ + void __iomem *d_third_plane_dpb_stride_size;/* only v8 */ + void __iomem *d_first_plane_dpb_size; + void __iomem *d_second_plane_dpb_size; + void __iomem *d_third_plane_dpb_size;/* only v8 */ + void __iomem *d_mv_buffer_size; + void __iomem *d_first_plane_dpb; + void __iomem *d_second_plane_dpb; + void __iomem *d_third_plane_dpb; + void __iomem *d_mv_buffer; + void __iomem *d_scratch_buffer_addr; + void __iomem *d_scratch_buffer_size; + void __iomem *d_metadata_buffer_addr; + void __iomem *d_metadata_buffer_size; + void __iomem *d_nal_start_options;/* v7 and v8 */ + void __iomem *d_cpb_buffer_addr; + void __iomem *d_cpb_buffer_size; + void __iomem *d_available_dpb_flag_upper; + void __iomem *d_available_dpb_flag_lower; + void __iomem *d_cpb_buffer_offset; + void __iomem *d_slice_if_enable; + void __iomem *d_picture_tag; + void __iomem *d_stream_data_size; + void __iomem *d_dynamic_dpb_flag_upper;/* v7 and v8 */ + void __iomem *d_dynamic_dpb_flag_lower;/* v7 and v8 */ + void __iomem *d_display_frame_width; + void __iomem *d_display_frame_height; + void __iomem *d_display_status; + void __iomem *d_display_first_plane_addr; + void __iomem *d_display_second_plane_addr; + void __iomem *d_display_third_plane_addr;/* only v8 */ + void __iomem *d_display_frame_type; + void __iomem *d_display_crop_info1; + void __iomem *d_display_crop_info2; + void __iomem *d_display_picture_profile; + void __iomem *d_display_luma_crc;/* v7 and v8 */ + void __iomem *d_display_chroma0_crc;/* v7 and v8 */ + void __iomem *d_display_chroma1_crc;/* only v8 */ + void __iomem *d_display_luma_crc_top;/* only v6 */ + void __iomem *d_display_chroma_crc_top;/* only v6 */ + void __iomem *d_display_luma_crc_bot;/* only v6 */ + void __iomem *d_display_chroma_crc_bot;/* only v6 */ + void __iomem *d_display_aspect_ratio; + void __iomem *d_display_extended_ar; + void __iomem *d_decoded_frame_width; + void __iomem *d_decoded_frame_height; + void __iomem *d_decoded_status; + void __iomem *d_decoded_first_plane_addr; + void __iomem *d_decoded_second_plane_addr; + void __iomem *d_decoded_third_plane_addr;/* only v8 */ + void __iomem *d_decoded_frame_type; + void __iomem *d_decoded_crop_info1; + void __iomem *d_decoded_crop_info2; + void __iomem *d_decoded_picture_profile; + void __iomem *d_decoded_nal_size; + void __iomem *d_decoded_luma_crc; + void __iomem *d_decoded_chroma0_crc; + void __iomem *d_decoded_chroma1_crc;/* only v8 */ + void __iomem *d_ret_picture_tag_top; + void __iomem *d_ret_picture_tag_bot; + void __iomem *d_ret_picture_time_top; + void __iomem *d_ret_picture_time_bot; + void __iomem *d_chroma_format; + void __iomem *d_vc1_info;/* v7 and v8 */ + void __iomem *d_mpeg4_info; + void __iomem *d_h264_info; + void __iomem *d_metadata_addr_concealed_mb; + void __iomem *d_metadata_size_concealed_mb; + void __iomem *d_metadata_addr_vc1_param; + void __iomem *d_metadata_size_vc1_param; + void __iomem *d_metadata_addr_sei_nal; + void __iomem *d_metadata_size_sei_nal; + void __iomem *d_metadata_addr_vui; + void __iomem *d_metadata_size_vui; + void __iomem *d_metadata_addr_mvcvui;/* v7 and v8 */ + void __iomem *d_metadata_size_mvcvui;/* v7 and v8 */ + void __iomem *d_mvc_view_id; + void __iomem *d_frame_pack_sei_avail; + void __iomem *d_frame_pack_arrgment_id; + void __iomem *d_frame_pack_sei_info; + void __iomem *d_frame_pack_grid_pos; + void __iomem *d_display_recovery_sei_info;/* v7 and v8 */ + void __iomem *d_decoded_recovery_sei_info;/* v7 and v8 */ + void __iomem *d_display_first_addr;/* only v7 */ + void __iomem *d_display_second_addr;/* only v7 */ + void __iomem *d_display_third_addr;/* only v7 */ + void __iomem *d_decoded_first_addr;/* only v7 */ + void __iomem *d_decoded_second_addr;/* only v7 */ + void __iomem *d_decoded_third_addr;/* only v7 */ + void __iomem *d_used_dpb_flag_upper;/* v7 and v8 */ + void __iomem *d_used_dpb_flag_lower;/* v7 and v8 */ /* encoder registers */ - volatile void __iomem *e_frame_width; - volatile void __iomem *e_frame_height; - volatile void __iomem *e_cropped_frame_width; - volatile void __iomem *e_cropped_frame_height; - volatile void __iomem *e_frame_crop_offset; - volatile void __iomem *e_enc_options; - volatile void __iomem *e_picture_profile; - volatile void __iomem *e_vbv_buffer_size; - volatile void __iomem *e_vbv_init_delay; - volatile void __iomem *e_fixed_picture_qp; - volatile void __iomem *e_rc_config; - volatile void __iomem *e_rc_qp_bound; - volatile void __iomem *e_rc_qp_bound_pb;/* v7 and v8 */ - volatile void __iomem *e_rc_mode; - volatile void __iomem *e_mb_rc_config; - volatile void __iomem *e_padding_ctrl; - volatile void __iomem *e_air_threshold; - volatile void __iomem *e_mv_hor_range; - volatile void __iomem *e_mv_ver_range; - volatile void __iomem *e_num_dpb; - volatile void __iomem *e_luma_dpb; - volatile void __iomem *e_chroma_dpb; - volatile void __iomem *e_me_buffer; - volatile void __iomem *e_scratch_buffer_addr; - volatile void __iomem *e_scratch_buffer_size; - volatile void __iomem *e_tmv_buffer0; - volatile void __iomem *e_tmv_buffer1; - volatile void __iomem *e_ir_buffer_addr;/* v7 and v8 */ - volatile void __iomem *e_source_first_plane_addr; - volatile void __iomem *e_source_second_plane_addr; - volatile void __iomem *e_source_third_plane_addr;/* v7 and v8 */ - volatile void __iomem *e_source_first_plane_stride;/* v7 and v8 */ - volatile void __iomem *e_source_second_plane_stride;/* v7 and v8 */ - volatile void __iomem *e_source_third_plane_stride;/* v7 and v8 */ - volatile void __iomem *e_stream_buffer_addr; - volatile void __iomem *e_stream_buffer_size; - volatile void __iomem *e_roi_buffer_addr; - volatile void __iomem *e_param_change; - volatile void __iomem *e_ir_size; - volatile void __iomem *e_gop_config; - volatile void __iomem *e_mslice_mode; - volatile void __iomem *e_mslice_size_mb; - volatile void __iomem *e_mslice_size_bits; - volatile void __iomem *e_frame_insertion; - volatile void __iomem *e_rc_frame_rate; - volatile void __iomem *e_rc_bit_rate; - volatile void __iomem *e_rc_roi_ctrl; - volatile void __iomem *e_picture_tag; - volatile void __iomem *e_bit_count_enable; - volatile void __iomem *e_max_bit_count; - volatile void __iomem *e_min_bit_count; - volatile void __iomem *e_metadata_buffer_addr; - volatile void __iomem *e_metadata_buffer_size; - volatile void __iomem *e_encoded_source_first_plane_addr; - volatile void __iomem *e_encoded_source_second_plane_addr; - volatile void __iomem *e_encoded_source_third_plane_addr;/* v7 and v8 */ - volatile void __iomem *e_stream_size; - volatile void __iomem *e_slice_type; - volatile void __iomem *e_picture_count; - volatile void __iomem *e_ret_picture_tag; - volatile void __iomem *e_stream_buffer_write_pointer; /* only v6 */ - volatile void __iomem *e_recon_luma_dpb_addr; - volatile void __iomem *e_recon_chroma_dpb_addr; - volatile void __iomem *e_metadata_addr_enc_slice; - volatile void __iomem *e_metadata_size_enc_slice; - volatile void __iomem *e_mpeg4_options; - volatile void __iomem *e_mpeg4_hec_period; - volatile void __iomem *e_aspect_ratio; - volatile void __iomem *e_extended_sar; - volatile void __iomem *e_h264_options; - volatile void __iomem *e_h264_options_2;/* v7 and v8 */ - volatile void __iomem *e_h264_lf_alpha_offset; - volatile void __iomem *e_h264_lf_beta_offset; - volatile void __iomem *e_h264_i_period; - volatile void __iomem *e_h264_fmo_slice_grp_map_type; - volatile void __iomem *e_h264_fmo_num_slice_grp_minus1; - volatile void __iomem *e_h264_fmo_slice_grp_change_dir; - volatile void __iomem *e_h264_fmo_slice_grp_change_rate_minus1; - volatile void __iomem *e_h264_fmo_run_length_minus1_0; - volatile void __iomem *e_h264_aso_slice_order_0; - volatile void __iomem *e_h264_chroma_qp_offset; - volatile void __iomem *e_h264_num_t_layer; - volatile void __iomem *e_h264_hierarchical_qp_layer0; - volatile void __iomem *e_h264_frame_packing_sei_info; - volatile void __iomem *e_h264_nal_control;/* v7 and v8 */ - volatile void __iomem *e_mvc_frame_qp_view1; - volatile void __iomem *e_mvc_rc_bit_rate_view1; - volatile void __iomem *e_mvc_rc_qbound_view1; - volatile void __iomem *e_mvc_rc_mode_view1; - volatile void __iomem *e_mvc_inter_view_prediction_on; - volatile void __iomem *e_vp8_options;/* v7 and v8 */ - volatile void __iomem *e_vp8_filter_options;/* v7 and v8 */ - volatile void __iomem *e_vp8_golden_frame_option;/* v7 and v8 */ - volatile void __iomem *e_vp8_num_t_layer;/* v7 and v8 */ - volatile void __iomem *e_vp8_hierarchical_qp_layer0;/* v7 and v8 */ - volatile void __iomem *e_vp8_hierarchical_qp_layer1;/* v7 and v8 */ - volatile void __iomem *e_vp8_hierarchical_qp_layer2;/* v7 and v8 */ + void __iomem *e_frame_width; + void __iomem *e_frame_height; + void __iomem *e_cropped_frame_width; + void __iomem *e_cropped_frame_height; + void __iomem *e_frame_crop_offset; + void __iomem *e_enc_options; + void __iomem *e_picture_profile; + void __iomem *e_vbv_buffer_size; + void __iomem *e_vbv_init_delay; + void __iomem *e_fixed_picture_qp; + void __iomem *e_rc_config; + void __iomem *e_rc_qp_bound; + void __iomem *e_rc_qp_bound_pb;/* v7 and v8 */ + void __iomem *e_rc_mode; + void __iomem *e_mb_rc_config; + void __iomem *e_padding_ctrl; + void __iomem *e_air_threshold; + void __iomem *e_mv_hor_range; + void __iomem *e_mv_ver_range; + void __iomem *e_num_dpb; + void __iomem *e_luma_dpb; + void __iomem *e_chroma_dpb; + void __iomem *e_me_buffer; + void __iomem *e_scratch_buffer_addr; + void __iomem *e_scratch_buffer_size; + void __iomem *e_tmv_buffer0; + void __iomem *e_tmv_buffer1; + void __iomem *e_ir_buffer_addr;/* v7 and v8 */ + void __iomem *e_source_first_plane_addr; + void __iomem *e_source_second_plane_addr; + void __iomem *e_source_third_plane_addr;/* v7 and v8 */ + void __iomem *e_source_first_plane_stride;/* v7 and v8 */ + void __iomem *e_source_second_plane_stride;/* v7 and v8 */ + void __iomem *e_source_third_plane_stride;/* v7 and v8 */ + void __iomem *e_stream_buffer_addr; + void __iomem *e_stream_buffer_size; + void __iomem *e_roi_buffer_addr; + void __iomem *e_param_change; + void __iomem *e_ir_size; + void __iomem *e_gop_config; + void __iomem *e_mslice_mode; + void __iomem *e_mslice_size_mb; + void __iomem *e_mslice_size_bits; + void __iomem *e_frame_insertion; + void __iomem *e_rc_frame_rate; + void __iomem *e_rc_bit_rate; + void __iomem *e_rc_roi_ctrl; + void __iomem *e_picture_tag; + void __iomem *e_bit_count_enable; + void __iomem *e_max_bit_count; + void __iomem *e_min_bit_count; + void __iomem *e_metadata_buffer_addr; + void __iomem *e_metadata_buffer_size; + void __iomem *e_encoded_source_first_plane_addr; + void __iomem *e_encoded_source_second_plane_addr; + void __iomem *e_encoded_source_third_plane_addr;/* v7 and v8 */ + void __iomem *e_stream_size; + void __iomem *e_slice_type; + void __iomem *e_picture_count; + void __iomem *e_ret_picture_tag; + void __iomem *e_stream_buffer_write_pointer; /* only v6 */ + void __iomem *e_recon_luma_dpb_addr; + void __iomem *e_recon_chroma_dpb_addr; + void __iomem *e_metadata_addr_enc_slice; + void __iomem *e_metadata_size_enc_slice; + void __iomem *e_mpeg4_options; + void __iomem *e_mpeg4_hec_period; + void __iomem *e_aspect_ratio; + void __iomem *e_extended_sar; + void __iomem *e_h264_options; + void __iomem *e_h264_options_2;/* v7 and v8 */ + void __iomem *e_h264_lf_alpha_offset; + void __iomem *e_h264_lf_beta_offset; + void __iomem *e_h264_i_period; + void __iomem *e_h264_fmo_slice_grp_map_type; + void __iomem *e_h264_fmo_num_slice_grp_minus1; + void __iomem *e_h264_fmo_slice_grp_change_dir; + void __iomem *e_h264_fmo_slice_grp_change_rate_minus1; + void __iomem *e_h264_fmo_run_length_minus1_0; + void __iomem *e_h264_aso_slice_order_0; + void __iomem *e_h264_chroma_qp_offset; + void __iomem *e_h264_num_t_layer; + void __iomem *e_h264_hierarchical_qp_layer0; + void __iomem *e_h264_frame_packing_sei_info; + void __iomem *e_h264_nal_control;/* v7 and v8 */ + void __iomem *e_mvc_frame_qp_view1; + void __iomem *e_mvc_rc_bit_rate_view1; + void __iomem *e_mvc_rc_qbound_view1; + void __iomem *e_mvc_rc_mode_view1; + void __iomem *e_mvc_inter_view_prediction_on; + void __iomem *e_vp8_options;/* v7 and v8 */ + void __iomem *e_vp8_filter_options;/* v7 and v8 */ + void __iomem *e_vp8_golden_frame_option;/* v7 and v8 */ + void __iomem *e_vp8_num_t_layer;/* v7 and v8 */ + void __iomem *e_vp8_hierarchical_qp_layer0;/* v7 and v8 */ + void __iomem *e_vp8_hierarchical_qp_layer1;/* v7 and v8 */ + void __iomem *e_vp8_hierarchical_qp_layer2;/* v7 and v8 */ }; struct s5p_mfc_hw_ops { @@ -281,28 +281,14 @@ struct s5p_mfc_hw_ops { void (*release_dev_context_buffer)(struct s5p_mfc_dev *dev); void (*dec_calc_dpb_size)(struct s5p_mfc_ctx *ctx); void (*enc_calc_src_size)(struct s5p_mfc_ctx *ctx); - int (*set_dec_stream_buffer)(struct s5p_mfc_ctx *ctx, - int buf_addr, unsigned int start_num_byte, - unsigned int buf_size); - int (*set_dec_frame_buffer)(struct s5p_mfc_ctx *ctx); int (*set_enc_stream_buffer)(struct s5p_mfc_ctx *ctx, unsigned long addr, unsigned int size); void (*set_enc_frame_buffer)(struct s5p_mfc_ctx *ctx, unsigned long y_addr, unsigned long c_addr); void (*get_enc_frame_buffer)(struct s5p_mfc_ctx *ctx, unsigned long *y_addr, unsigned long *c_addr); - int (*set_enc_ref_buffer)(struct s5p_mfc_ctx *ctx); - int (*init_decode)(struct s5p_mfc_ctx *ctx); - int (*init_encode)(struct s5p_mfc_ctx *ctx); - int (*encode_one_frame)(struct s5p_mfc_ctx *ctx); void (*try_run)(struct s5p_mfc_dev *dev); - void (*cleanup_queue)(struct list_head *lh, - struct vb2_queue *vq); void (*clear_int_flags)(struct s5p_mfc_dev *dev); - void (*write_info)(struct s5p_mfc_ctx *ctx, unsigned int data, - unsigned int ofs); - unsigned int (*read_info)(struct s5p_mfc_ctx *ctx, - unsigned long ofs); int (*get_dspl_y_adr)(struct s5p_mfc_dev *dev); int (*get_dec_y_adr)(struct s5p_mfc_dev *dev); int (*get_dspl_status)(struct s5p_mfc_dev *dev); @@ -313,7 +299,6 @@ struct s5p_mfc_hw_ops { int (*get_int_reason)(struct s5p_mfc_dev *dev); int (*get_int_err)(struct s5p_mfc_dev *dev); int (*err_dec)(unsigned int err); - int (*err_dspl)(unsigned int err); int (*get_img_width)(struct s5p_mfc_dev *dev); int (*get_img_height)(struct s5p_mfc_dev *dev); int (*get_dpb_count)(struct s5p_mfc_dev *dev); @@ -322,10 +307,6 @@ struct s5p_mfc_hw_ops { int (*get_enc_strm_size)(struct s5p_mfc_dev *dev); int (*get_enc_slice_type)(struct s5p_mfc_dev *dev); int (*get_enc_dpb_count)(struct s5p_mfc_dev *dev); - int (*get_enc_pic_count)(struct s5p_mfc_dev *dev); - int (*get_sei_avail_status)(struct s5p_mfc_ctx *ctx); - int (*get_mvc_num_views)(struct s5p_mfc_dev *dev); - int (*get_mvc_view_id)(struct s5p_mfc_dev *dev); unsigned int (*get_pic_type_top)(struct s5p_mfc_ctx *ctx); unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx); unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index 873c933bc7d4..81e1e4ce6c24 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -1153,27 +1153,6 @@ static int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx) return 0; } -static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev) -{ - unsigned long flags; - int new_ctx; - int cnt; - - spin_lock_irqsave(&dev->condlock, flags); - new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS; - cnt = 0; - while (!test_bit(new_ctx, &dev->ctx_work_bits)) { - new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS; - if (++cnt > MFC_NUM_CONTEXTS) { - /* No contexts to run */ - spin_unlock_irqrestore(&dev->condlock, flags); - return -EAGAIN; - } - } - spin_unlock_irqrestore(&dev->condlock, flags); - return new_ctx; -} - static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; @@ -1187,7 +1166,6 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) { struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *temp_vb; - unsigned long flags; if (ctx->state == MFCINST_FINISHING) { last_frame = MFC_DEC_LAST_FRAME; @@ -1197,11 +1175,9 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) return 0; } - spin_lock_irqsave(&dev->irqlock, flags); /* Frames are being decoded */ if (list_empty(&ctx->src_queue)) { mfc_debug(2, "No src buffers\n"); - spin_unlock_irqrestore(&dev->irqlock, flags); return -EAGAIN; } /* Get the next source buffer */ @@ -1210,7 +1186,6 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) s5p_mfc_set_dec_stream_buffer_v5(ctx, vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0), ctx->consumed_stream, temp_vb->b->vb2_buf.planes[0].bytesused); - spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) { last_frame = MFC_DEC_LAST_FRAME; @@ -1224,21 +1199,17 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; struct s5p_mfc_buf *dst_mb; struct s5p_mfc_buf *src_mb; unsigned long src_y_addr, src_c_addr, dst_addr; unsigned int dst_size; - spin_lock_irqsave(&dev->irqlock, flags); if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) { mfc_debug(2, "no src buffers\n"); - spin_unlock_irqrestore(&dev->irqlock, flags); return -EAGAIN; } if (list_empty(&ctx->dst_queue)) { mfc_debug(2, "no dst buffers\n"); - spin_unlock_irqrestore(&dev->irqlock, flags); return -EAGAIN; } if (list_empty(&ctx->src_queue)) { @@ -1270,7 +1241,6 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0); dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0); s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size); - spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; mfc_debug(2, "encoding buffer with index=%d state=%d\n", src_mb ? src_mb->b->vb2_buf.index : -1, ctx->state); @@ -1281,11 +1251,9 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; struct s5p_mfc_buf *temp_vb; /* Initializing decoding - parsing header */ - spin_lock_irqsave(&dev->irqlock, flags); mfc_debug(2, "Preparing to init decoding\n"); temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); s5p_mfc_set_dec_desc_buffer(ctx); @@ -1294,7 +1262,6 @@ static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) s5p_mfc_set_dec_stream_buffer_v5(ctx, vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0), 0, temp_vb->b->vb2_buf.planes[0].bytesused); - spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; s5p_mfc_init_decode_v5(ctx); } @@ -1302,18 +1269,15 @@ static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; struct s5p_mfc_buf *dst_mb; unsigned long dst_addr; unsigned int dst_size; s5p_mfc_set_enc_ref_buffer_v5(ctx); - spin_lock_irqsave(&dev->irqlock, flags); dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0); dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0); s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size); - spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; s5p_mfc_init_encode_v5(ctx); } @@ -1321,7 +1285,6 @@ static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx) static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; struct s5p_mfc_buf *temp_vb; int ret; @@ -1335,11 +1298,9 @@ static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx) "before starting processing\n"); return -EAGAIN; } - spin_lock_irqsave(&dev->irqlock, flags); if (list_empty(&ctx->src_queue)) { mfc_err("Header has been deallocated in the middle of" " initialization\n"); - spin_unlock_irqrestore(&dev->irqlock, flags); return -EIO; } temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); @@ -1348,7 +1309,6 @@ static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx) s5p_mfc_set_dec_stream_buffer_v5(ctx, vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0), 0, temp_vb->b->vb2_buf.planes[0].bytesused); - spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; ret = s5p_mfc_set_dec_frame_buffer_v5(ctx); if (ret) { @@ -1472,21 +1432,6 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev) } } - -static void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq) -{ - struct s5p_mfc_buf *b; - int i; - - while (!list_empty(lh)) { - b = list_entry(lh->next, struct s5p_mfc_buf, list); - for (i = 0; i < b->b->vb2_buf.num_planes; i++) - vb2_set_plane_payload(&b->b->vb2_buf, i, 0); - vb2_buffer_done(&b->b->vb2_buf, VB2_BUF_STATE_ERROR); - list_del(&b->list); - } -} - static void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev) { mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT); @@ -1590,11 +1535,6 @@ static int s5p_mfc_err_dec_v5(unsigned int err) return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT; } -static int s5p_mfc_err_dspl_v5(unsigned int err) -{ - return (err & S5P_FIMV_ERR_DSPL_MASK) >> S5P_FIMV_ERR_DSPL_SHIFT; -} - static int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev) { return mfc_read(dev, S5P_FIMV_SI_HRESOL); @@ -1636,26 +1576,6 @@ static int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev) return -1; } -static int s5p_mfc_get_enc_pic_count_v5(struct s5p_mfc_dev *dev) -{ - return mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT); -} - -static int s5p_mfc_get_sei_avail_status_v5(struct s5p_mfc_ctx *ctx) -{ - return s5p_mfc_read_info_v5(ctx, FRAME_PACK_SEI_AVAIL); -} - -static int s5p_mfc_get_mvc_num_views_v5(struct s5p_mfc_dev *dev) -{ - return -1; -} - -static int s5p_mfc_get_mvc_view_id_v5(struct s5p_mfc_dev *dev) -{ - return -1; -} - static unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx) { return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP); @@ -1688,20 +1608,11 @@ static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = { .release_dev_context_buffer = s5p_mfc_release_dev_context_buffer_v5, .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v5, .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v5, - .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v5, - .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v5, .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v5, .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v5, .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v5, - .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v5, - .init_decode = s5p_mfc_init_decode_v5, - .init_encode = s5p_mfc_init_encode_v5, - .encode_one_frame = s5p_mfc_encode_one_frame_v5, .try_run = s5p_mfc_try_run_v5, - .cleanup_queue = s5p_mfc_cleanup_queue_v5, .clear_int_flags = s5p_mfc_clear_int_flags_v5, - .write_info = s5p_mfc_write_info_v5, - .read_info = s5p_mfc_read_info_v5, .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v5, .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v5, .get_dspl_status = s5p_mfc_get_dspl_status_v5, @@ -1712,7 +1623,6 @@ static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = { .get_int_reason = s5p_mfc_get_int_reason_v5, .get_int_err = s5p_mfc_get_int_err_v5, .err_dec = s5p_mfc_err_dec_v5, - .err_dspl = s5p_mfc_err_dspl_v5, .get_img_width = s5p_mfc_get_img_width_v5, .get_img_height = s5p_mfc_get_img_height_v5, .get_dpb_count = s5p_mfc_get_dpb_count_v5, @@ -1721,10 +1631,6 @@ static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = { .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v5, .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v5, .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v5, - .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v5, - .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v5, - .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v5, - .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v5, .get_pic_type_top = s5p_mfc_get_pic_type_top_v5, .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5, .get_crop_info_h = s5p_mfc_get_crop_info_h_v5, diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index b95845347348..d6f207e859ab 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -505,7 +505,7 @@ static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) } writel(ctx->inst_no, mfc_regs->instance_id); - s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_INIT_BUFS_V6, NULL); mfc_debug(2, "After setting buffers.\n"); @@ -603,7 +603,7 @@ static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) } writel(ctx->inst_no, mfc_regs->instance_id); - s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_INIT_BUFS_V6, NULL); mfc_debug_leave(); @@ -1378,7 +1378,7 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) writel(ctx->sei_fp_parse & 0x1, mfc_regs->d_sei_enable); writel(ctx->inst_no, mfc_regs->instance_id); - s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_SEQ_HEADER_V6, NULL); mfc_debug_leave(); @@ -1393,7 +1393,7 @@ static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush) if (flush) { dev->curr_ctx = ctx->num; writel(ctx->inst_no, mfc_regs->instance_id); - s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_H2R_CMD_FLUSH_V6, NULL); } } @@ -1413,11 +1413,11 @@ static int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx, * is the last frame or not. */ switch (last_frame) { case 0: - s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_FRAME_START_V6, NULL); break; case 1: - s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_LAST_FRAME_V6, NULL); break; default: @@ -1455,7 +1455,7 @@ static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) } writel(ctx->inst_no, mfc_regs->instance_id); - s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, S5P_FIMV_CH_SEQ_HEADER_V6, NULL); return 0; @@ -1500,37 +1500,13 @@ static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx) cmd = S5P_FIMV_CH_LAST_FRAME_V6; writel(ctx->inst_no, mfc_regs->instance_id); - s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, cmd, NULL); + s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, cmd, NULL); mfc_debug(2, "--\n"); return 0; } -static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev) -{ - unsigned long flags; - int new_ctx; - int cnt; - - spin_lock_irqsave(&dev->condlock, flags); - mfc_debug(2, "Previous context: %d (bits %08lx)\n", dev->curr_ctx, - dev->ctx_work_bits); - new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS; - cnt = 0; - while (!test_bit(new_ctx, &dev->ctx_work_bits)) { - new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS; - cnt++; - if (cnt > MFC_NUM_CONTEXTS) { - /* No contexts to run */ - spin_unlock_irqrestore(&dev->condlock, flags); - return -EAGAIN; - } - } - spin_unlock_irqrestore(&dev->condlock, flags); - return new_ctx; -} - static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; @@ -1544,7 +1520,6 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *temp_vb; - unsigned long flags; int last_frame = 0; if (ctx->state == MFCINST_FINISHING) { @@ -1556,11 +1531,9 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) return 0; } - spin_lock_irqsave(&dev->irqlock, flags); /* Frames are being decoded */ if (list_empty(&ctx->src_queue)) { mfc_debug(2, "No src buffers.\n"); - spin_unlock_irqrestore(&dev->irqlock, flags); return -EAGAIN; } /* Get the next source buffer */ @@ -1570,7 +1543,6 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0), ctx->consumed_stream, temp_vb->b->vb2_buf.planes[0].bytesused); - spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) { @@ -1586,7 +1558,6 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; struct s5p_mfc_buf *dst_mb; struct s5p_mfc_buf *src_mb; unsigned long src_y_addr, src_c_addr, dst_addr; @@ -1595,17 +1566,13 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) */ unsigned int dst_size; - spin_lock_irqsave(&dev->irqlock, flags); - if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) { mfc_debug(2, "no src buffers.\n"); - spin_unlock_irqrestore(&dev->irqlock, flags); return -EAGAIN; } if (list_empty(&ctx->dst_queue)) { mfc_debug(2, "no dst buffers.\n"); - spin_unlock_irqrestore(&dev->irqlock, flags); return -EAGAIN; } @@ -1639,8 +1606,6 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size); - spin_unlock_irqrestore(&dev->irqlock, flags); - dev->curr_ctx = ctx->num; s5p_mfc_encode_one_frame_v6(ctx); @@ -1650,18 +1615,15 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; struct s5p_mfc_buf *temp_vb; /* Initializing decoding - parsing header */ - spin_lock_irqsave(&dev->irqlock, flags); mfc_debug(2, "Preparing to init decoding.\n"); temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); mfc_debug(2, "Header size: %d\n", temp_vb->b->vb2_buf.planes[0].bytesused); s5p_mfc_set_dec_stream_buffer_v6(ctx, vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0), 0, temp_vb->b->vb2_buf.planes[0].bytesused); - spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; s5p_mfc_init_decode_v6(ctx); } @@ -1669,18 +1631,14 @@ static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; struct s5p_mfc_buf *dst_mb; unsigned long dst_addr; unsigned int dst_size; - spin_lock_irqsave(&dev->irqlock, flags); - dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0); dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0); s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size); - spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; s5p_mfc_init_encode_v6(ctx); } @@ -1846,21 +1804,6 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) } } - -static void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq) -{ - struct s5p_mfc_buf *b; - int i; - - while (!list_empty(lh)) { - b = list_entry(lh->next, struct s5p_mfc_buf, list); - for (i = 0; i < b->b->vb2_buf.num_planes; i++) - vb2_set_plane_payload(&b->b->vb2_buf, i, 0); - vb2_buffer_done(&b->b->vb2_buf, VB2_BUF_STATE_ERROR); - list_del(&b->list); - } -} - static void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev) { const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; @@ -1868,14 +1811,6 @@ static void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev) writel(0, mfc_regs->risc2host_int); } -static void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data, - unsigned int ofs) -{ - s5p_mfc_clock_on(); - writel(data, (void __iomem *)((unsigned long)ofs)); - s5p_mfc_clock_off(); -} - static unsigned int s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned long ofs) { @@ -1942,11 +1877,6 @@ static int s5p_mfc_err_dec_v6(unsigned int err) return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6; } -static int s5p_mfc_err_dspl_v6(unsigned int err) -{ - return (err & S5P_FIMV_ERR_DSPL_MASK_V6) >> S5P_FIMV_ERR_DSPL_SHIFT_V6; -} - static int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev) { return readl(dev->mfc_regs->d_display_frame_width); @@ -1987,27 +1917,6 @@ static int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev) return readl(dev->mfc_regs->e_slice_type); } -static int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev) -{ - return readl(dev->mfc_regs->e_picture_count); -} - -static int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx) -{ - struct s5p_mfc_dev *dev = ctx->dev; - return readl(dev->mfc_regs->d_frame_pack_sei_avail); -} - -static int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev) -{ - return readl(dev->mfc_regs->d_mvc_num_views); -} - -static int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev) -{ - return readl(dev->mfc_regs->d_mvc_view_id); -} - static unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx) { return s5p_mfc_read_info_v6(ctx, @@ -2282,20 +2191,11 @@ static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = { s5p_mfc_release_dev_context_buffer_v6, .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v6, .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v6, - .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v6, - .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v6, .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v6, .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v6, .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v6, - .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v6, - .init_decode = s5p_mfc_init_decode_v6, - .init_encode = s5p_mfc_init_encode_v6, - .encode_one_frame = s5p_mfc_encode_one_frame_v6, .try_run = s5p_mfc_try_run_v6, - .cleanup_queue = s5p_mfc_cleanup_queue_v6, .clear_int_flags = s5p_mfc_clear_int_flags_v6, - .write_info = s5p_mfc_write_info_v6, - .read_info = s5p_mfc_read_info_v6, .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v6, .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v6, .get_dspl_status = s5p_mfc_get_dspl_status_v6, @@ -2306,7 +2206,6 @@ static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = { .get_int_reason = s5p_mfc_get_int_reason_v6, .get_int_err = s5p_mfc_get_int_err_v6, .err_dec = s5p_mfc_err_dec_v6, - .err_dspl = s5p_mfc_err_dspl_v6, .get_img_width = s5p_mfc_get_img_width_v6, .get_img_height = s5p_mfc_get_img_height_v6, .get_dpb_count = s5p_mfc_get_dpb_count_v6, @@ -2315,10 +2214,6 @@ static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = { .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v6, .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v6, .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v6, - .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v6, - .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v6, - .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v6, - .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v6, .get_pic_type_top = s5p_mfc_get_pic_type_top_v6, .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v6, .get_crop_info_h = s5p_mfc_get_crop_info_h_v6, diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index 79940757b34f..e71b13e40f59 100644 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c @@ -33,7 +33,7 @@ #include <linux/regulator/consumer.h> #include <linux/v4l2-dv-timings.h> -#include <media/s5p_hdmi.h> +#include <linux/platform_data/media/s5p_hdmi.h> #include <media/v4l2-common.h> #include <media/v4l2-dev.h> #include <media/v4l2-device.h> @@ -627,7 +627,7 @@ static int hdmi_s_dv_timings(struct v4l2_subdev *sd, for (i = 0; i < ARRAY_SIZE(hdmi_timings); i++) if (v4l2_match_dv_timings(&hdmi_timings[i].dv_timings, - timings, 0)) + timings, 0, false)) break; if (i == ARRAY_SIZE(hdmi_timings)) { dev_err(dev, "timings not supported\n"); diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index dc1c679e136c..d9e7f030294c 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c @@ -881,7 +881,7 @@ static const struct v4l2_file_operations mxr_fops = { .unlocked_ioctl = video_ioctl2, }; -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/platform/s5p-tv/sii9234_drv.c b/drivers/media/platform/s5p-tv/sii9234_drv.c index 8d171310af8f..0a97f9ab4f76 100644 --- a/drivers/media/platform/s5p-tv/sii9234_drv.c +++ b/drivers/media/platform/s5p-tv/sii9234_drv.c @@ -23,7 +23,7 @@ #include <linux/regulator/machine.h> #include <linux/slab.h> -#include <media/sii9234.h> +#include <linux/platform_data/media/sii9234.h> #include <media/v4l2-subdev.h> MODULE_AUTHOR("Tomasz Stanislawski <t.stanislaws@samsung.com>"); diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index d6ab33e7060a..82b5d69b87fa 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -865,32 +865,14 @@ static const struct v4l2_ioctl_ops sh_veu_ioctl_ops = { /* ========== Queue operations ========== */ static int sh_veu_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *f = parg; struct sh_veu_dev *veu = vb2_get_drv_priv(vq); - struct sh_veu_vfmt *vfmt; - unsigned int size, count = *nbuffers; - - if (f) { - const struct v4l2_pix_format *pix = &f->fmt.pix; - const struct sh_veu_format *fmt = sh_veu_find_fmt(f); - struct v4l2_format ftmp = *f; - - if (fmt->fourcc != pix->pixelformat) - return -EINVAL; - sh_veu_try_fmt(&ftmp, fmt); - if (ftmp.fmt.pix.width != pix->width || - ftmp.fmt.pix.height != pix->height) - return -EINVAL; - size = pix->bytesperline ? pix->bytesperline * pix->height * fmt->depth / fmt->ydepth : - pix->width * pix->height * fmt->depth / fmt->ydepth; - } else { - vfmt = sh_veu_get_vfmt(veu, vq->type); - size = vfmt->bytesperline * vfmt->frame.height * vfmt->fmt->depth / vfmt->fmt->ydepth; - } + struct sh_veu_vfmt *vfmt = sh_veu_get_vfmt(veu, vq->type); + unsigned int count = *nbuffers; + unsigned int size = vfmt->bytesperline * vfmt->frame.height * + vfmt->fmt->depth / vfmt->fmt->ydepth; if (count < 2) *nbuffers = count = 2; @@ -900,6 +882,11 @@ static int sh_veu_queue_setup(struct vb2_queue *vq, *nbuffers = count; } + if (*nplanes) { + alloc_ctxs[0] = veu->alloc_ctx; + return sizes[0] < size ? -EINVAL : 0; + } + *nplanes = 1; sizes[0] = size; alloc_ctxs[0] = veu->alloc_ctx; @@ -1107,7 +1094,7 @@ static irqreturn_t sh_veu_isr(int irq, void *dev_id) if (!src || !dst) return IRQ_NONE; - dst->timestamp = src->timestamp; + 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; diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index 2231f8922df3..115740498274 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -22,7 +22,7 @@ #include <linux/videodev2.h> #include <linux/module.h> -#include <media/sh_vou.h> +#include <media/drv-intf/sh_vou.h> #include <media/v4l2-common.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> @@ -243,22 +243,21 @@ static void sh_vou_stream_config(struct sh_vou_device *vou_dev) } /* Locking: caller holds fop_lock mutex */ -static int sh_vou_queue_setup(struct vb2_queue *vq, const void *parg, +static int sh_vou_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq); struct v4l2_pix_format *pix = &vou_dev->pix; int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8; dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); - if (fmt && fmt->fmt.pix.sizeimage < pix->height * bytes_per_line) - return -EINVAL; - *nplanes = 1; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : pix->height * bytes_per_line; alloc_ctxs[0] = vou_dev->alloc_ctx; + if (*nplanes) + return sizes[0] < pix->height * bytes_per_line ? -EINVAL : 0; + *nplanes = 1; + sizes[0] = pix->height * bytes_per_line; return 0; } @@ -1071,7 +1070,7 @@ static irqreturn_t sh_vou_isr(int irq, void *dev_id) list_del(&vb->list); - v4l2_get_timestamp(&vb->vb.timestamp); + vb->vb.vb2_buf.timestamp = ktime_get_ns(); vb->vb.sequence = vou_dev->sequence++; vb->vb.field = V4L2_FIELD_INTERLACED; vb2_buffer_done(&vb->vb.vb2_buf, VB2_BUF_STATE_DONE); diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index 454f68f0cdad..c398b285180c 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c @@ -24,7 +24,7 @@ #include <linux/slab.h> #include <media/soc_camera.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> #include <media/v4l2-of.h> #include <media/videobuf2-dma-contig.h> @@ -79,6 +79,7 @@ struct atmel_isi { dma_addr_t fb_descriptors_phys; struct list_head dma_desc_head; struct isi_dma_desc dma_desc[MAX_BUFFER_NUM]; + bool enable_preview_path; struct completion complete; /* ISI peripherial clock */ @@ -103,13 +104,55 @@ static u32 isi_readl(struct atmel_isi *isi, u32 reg) return readl(isi->regs + reg); } +static u32 setup_cfg2_yuv_swap(struct atmel_isi *isi, + const struct soc_camera_format_xlate *xlate) +{ + if (xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUYV) { + /* all convert to YUYV */ + switch (xlate->code) { + case MEDIA_BUS_FMT_VYUY8_2X8: + return ISI_CFG2_YCC_SWAP_MODE_3; + case MEDIA_BUS_FMT_UYVY8_2X8: + return ISI_CFG2_YCC_SWAP_MODE_2; + case MEDIA_BUS_FMT_YVYU8_2X8: + return ISI_CFG2_YCC_SWAP_MODE_1; + } + } else if (xlate->host_fmt->fourcc == V4L2_PIX_FMT_RGB565) { + /* + * Preview path is enabled, it will convert UYVY to RGB format. + * But if sensor output format is not UYVY, we need to set + * YCC_SWAP_MODE to convert it as UYVY. + */ + switch (xlate->code) { + case MEDIA_BUS_FMT_VYUY8_2X8: + return ISI_CFG2_YCC_SWAP_MODE_1; + case MEDIA_BUS_FMT_YUYV8_2X8: + return ISI_CFG2_YCC_SWAP_MODE_2; + case MEDIA_BUS_FMT_YVYU8_2X8: + return ISI_CFG2_YCC_SWAP_MODE_3; + } + } + + /* + * By default, no swap for the codec path of Atmel ISI. So codec + * output is same as sensor's output. + * For instance, if sensor's output is YUYV, then codec outputs YUYV. + * And if sensor's output is UYVY, then codec outputs UYVY. + */ + return ISI_CFG2_YCC_SWAP_DEFAULT; +} + static void configure_geometry(struct atmel_isi *isi, u32 width, - u32 height, u32 code) + u32 height, const struct soc_camera_format_xlate *xlate) { - u32 cfg2; + u32 cfg2, psize; + u32 fourcc = xlate->host_fmt->fourcc; + + isi->enable_preview_path = fourcc == V4L2_PIX_FMT_RGB565 || + fourcc == V4L2_PIX_FMT_RGB32; /* According to sensor's output format to set cfg2 */ - switch (code) { + switch (xlate->code) { default: /* Grey */ case MEDIA_BUS_FMT_Y8_1X8: @@ -117,16 +160,11 @@ static void configure_geometry(struct atmel_isi *isi, u32 width, break; /* YUV */ case MEDIA_BUS_FMT_VYUY8_2X8: - cfg2 = ISI_CFG2_YCC_SWAP_MODE_3 | ISI_CFG2_COL_SPACE_YCbCr; - break; case MEDIA_BUS_FMT_UYVY8_2X8: - cfg2 = ISI_CFG2_YCC_SWAP_MODE_2 | ISI_CFG2_COL_SPACE_YCbCr; - break; case MEDIA_BUS_FMT_YVYU8_2X8: - cfg2 = ISI_CFG2_YCC_SWAP_MODE_1 | ISI_CFG2_COL_SPACE_YCbCr; - break; case MEDIA_BUS_FMT_YUYV8_2X8: - cfg2 = ISI_CFG2_YCC_SWAP_DEFAULT | ISI_CFG2_COL_SPACE_YCbCr; + cfg2 = ISI_CFG2_COL_SPACE_YCbCr | + setup_cfg2_yuv_swap(isi, xlate); break; /* RGB, TODO */ } @@ -139,6 +177,16 @@ static void configure_geometry(struct atmel_isi *isi, u32 width, cfg2 |= ((height - 1) << ISI_CFG2_IM_VSIZE_OFFSET) & ISI_CFG2_IM_VSIZE_MASK; isi_writel(isi, ISI_CFG2, cfg2); + + /* No down sampling, preview size equal to sensor output size */ + psize = ((width - 1) << ISI_PSIZE_PREV_HSIZE_OFFSET) & + ISI_PSIZE_PREV_HSIZE_MASK; + psize |= ((height - 1) << ISI_PSIZE_PREV_VSIZE_OFFSET) & + ISI_PSIZE_PREV_VSIZE_MASK; + isi_writel(isi, ISI_PSIZE, psize); + isi_writel(isi, ISI_PDECF, ISI_PDECF_NO_SAMPLING); + + return; } static bool is_supported(struct soc_camera_device *icd, @@ -151,8 +199,9 @@ static bool is_supported(struct soc_camera_device *icd, case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_YVYU: case V4L2_PIX_FMT_VYUY: + /* RGB */ + case V4L2_PIX_FMT_RGB565: return true; - /* RGB, TODO */ default: return false; } @@ -165,7 +214,7 @@ static irqreturn_t atmel_isi_handle_streaming(struct atmel_isi *isi) struct frame_buffer *buf = isi->active; list_del_init(&buf->list); - v4l2_get_timestamp(&vbuf->timestamp); + vbuf->vb2_buf.timestamp = ktime_get_ns(); vbuf->sequence = isi->sequence++; vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); } @@ -176,11 +225,19 @@ static irqreturn_t atmel_isi_handle_streaming(struct atmel_isi *isi) /* start next dma frame. */ isi->active = list_entry(isi->video_buffer_list.next, struct frame_buffer, list); - isi_writel(isi, ISI_DMA_C_DSCR, - (u32)isi->active->p_dma_desc->fbd_phys); - isi_writel(isi, ISI_DMA_C_CTRL, - ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE); - isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_C_CH); + if (!isi->enable_preview_path) { + isi_writel(isi, ISI_DMA_C_DSCR, + (u32)isi->active->p_dma_desc->fbd_phys); + isi_writel(isi, ISI_DMA_C_CTRL, + ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE); + isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_C_CH); + } else { + isi_writel(isi, ISI_DMA_P_DSCR, + (u32)isi->active->p_dma_desc->fbd_phys); + isi_writel(isi, ISI_DMA_P_CTRL, + ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE); + isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_P_CH); + } } return IRQ_HANDLED; } @@ -207,7 +264,8 @@ static irqreturn_t isi_interrupt(int irq, void *dev_id) isi_writel(isi, ISI_INTDIS, ISI_CTRL_DIS); ret = IRQ_HANDLED; } else { - if (likely(pending & ISI_SR_CXFR_DONE)) + if (likely(pending & ISI_SR_CXFR_DONE) || + likely(pending & ISI_SR_PXFR_DONE)) ret = atmel_isi_handle_streaming(isi); } @@ -245,7 +303,7 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset) /* ------------------------------------------------------------------ Videobuf operations ------------------------------------------------------------------*/ -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -352,21 +410,35 @@ static void start_dma(struct atmel_isi *isi, struct frame_buffer *buffer) ISI_SR_CXFR_DONE | ISI_SR_PXFR_DONE); /* Check if already in a frame */ - if (isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) { - dev_err(isi->soc_host.icd->parent, "Already in frame handling.\n"); - return; - } + if (!isi->enable_preview_path) { + if (isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) { + dev_err(isi->soc_host.icd->parent, "Already in frame handling.\n"); + return; + } - isi_writel(isi, ISI_DMA_C_DSCR, (u32)buffer->p_dma_desc->fbd_phys); - isi_writel(isi, ISI_DMA_C_CTRL, ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE); - isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_C_CH); + isi_writel(isi, ISI_DMA_C_DSCR, + (u32)buffer->p_dma_desc->fbd_phys); + isi_writel(isi, ISI_DMA_C_CTRL, + ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE); + isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_C_CH); + } else { + isi_writel(isi, ISI_DMA_P_DSCR, + (u32)buffer->p_dma_desc->fbd_phys); + isi_writel(isi, ISI_DMA_P_CTRL, + ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE); + isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_P_CH); + } cfg1 &= ~ISI_CFG1_FRATE_DIV_MASK; /* Enable linked list */ cfg1 |= isi->pdata.frate | ISI_CFG1_DISCR; - /* Enable codec path and ISI */ - ctrl = ISI_CTRL_CDC | ISI_CTRL_EN; + /* Enable ISI */ + ctrl = ISI_CTRL_EN; + + if (!isi->enable_preview_path) + ctrl |= ISI_CTRL_CDC; + isi_writel(isi, ISI_CTRL, ctrl); isi_writel(isi, ISI_CFG1, cfg1); } @@ -411,7 +483,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) isi_writel(isi, ISI_INTDIS, (u32)~0UL); configure_geometry(isi, icd->user_width, icd->user_height, - icd->current_fmt->code); + icd->current_fmt); spin_lock_irq(&isi->lock); /* Clear any pending interrupt */ @@ -443,15 +515,17 @@ static void stop_streaming(struct vb2_queue *vq) } spin_unlock_irq(&isi->lock); - timeout = jiffies + FRAME_INTERVAL_MILLI_SEC * HZ; - /* Wait until the end of the current frame. */ - while ((isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) && - time_before(jiffies, timeout)) - msleep(1); + if (!isi->enable_preview_path) { + timeout = jiffies + FRAME_INTERVAL_MILLI_SEC * HZ; + /* Wait until the end of the current frame. */ + while ((isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) && + time_before(jiffies, timeout)) + msleep(1); - if (time_after(jiffies, timeout)) - dev_err(icd->parent, - "Timeout waiting for finishing codec request\n"); + if (time_after(jiffies, timeout)) + dev_err(icd->parent, + "Timeout waiting for finishing codec request\n"); + } /* Disable interrupts */ isi_writel(isi, ISI_INTDIS, @@ -617,6 +691,14 @@ static const struct soc_mbus_pixelfmt isi_camera_formats[] = { .order = SOC_MBUS_ORDER_LE, .layout = SOC_MBUS_LAYOUT_PACKED, }, + { + .fourcc = V4L2_PIX_FMT_RGB565, + .name = "RGB565", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, }; /* This will be corrected as we get more formats */ @@ -673,7 +755,7 @@ static int isi_camera_get_formats(struct soc_camera_device *icd, struct soc_camera_format_xlate *xlate) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - int formats = 0, ret; + int formats = 0, ret, i, n; /* sensor format */ struct v4l2_subdev_mbus_code_enum code = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, @@ -707,11 +789,11 @@ static int isi_camera_get_formats(struct soc_camera_device *icd, case MEDIA_BUS_FMT_VYUY8_2X8: case MEDIA_BUS_FMT_YUYV8_2X8: case MEDIA_BUS_FMT_YVYU8_2X8: - formats++; - if (xlate) { - xlate->host_fmt = &isi_camera_formats[0]; + n = ARRAY_SIZE(isi_camera_formats); + formats += n; + for (i = 0; xlate && i < n; i++, xlate++) { + xlate->host_fmt = &isi_camera_formats[i]; xlate->code = code.code; - xlate++; dev_dbg(icd->parent, "Providing format %s using code %d\n", isi_camera_formats[0].name, code.code); } diff --git a/drivers/media/platform/soc_camera/atmel-isi.h b/drivers/media/platform/soc_camera/atmel-isi.h index 5acc771d2edc..0acb32a2b65c 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.h +++ b/drivers/media/platform/soc_camera/atmel-isi.h @@ -79,6 +79,16 @@ #define ISI_CFG2_IM_VSIZE_MASK (0x7FF << ISI_CFG2_IM_VSIZE_OFFSET) #define ISI_CFG2_IM_HSIZE_MASK (0x7FF << ISI_CFG2_IM_HSIZE_OFFSET) +/* Bitfields in PSIZE */ +#define ISI_PSIZE_PREV_VSIZE_OFFSET 0 +#define ISI_PSIZE_PREV_HSIZE_OFFSET 16 +#define ISI_PSIZE_PREV_VSIZE_MASK (0x3FF << ISI_PSIZE_PREV_VSIZE_OFFSET) +#define ISI_PSIZE_PREV_HSIZE_MASK (0x3FF << ISI_PSIZE_PREV_HSIZE_OFFSET) + +/* Bitfields in PDECF */ +#define ISI_PDECF_DEC_FACTOR_MASK (0xFF << 0) +#define ISI_PDECF_NO_SAMPLING (16) + /* Bitfields in CTRL */ /* Also using in SR(ISI_V2) */ #define ISI_CTRL_EN (1 << 0) diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c index 1f28d21a3c9a..48dd5b7851b5 100644 --- a/drivers/media/platform/soc_camera/mx2_camera.c +++ b/drivers/media/platform/soc_camera/mx2_camera.c @@ -35,11 +35,11 @@ #include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include <media/soc_camera.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> #include <linux/videodev2.h> -#include <linux/platform_data/camera-mx2.h> +#include <linux/platform_data/media/camera-mx2.h> #include <asm/dma.h> @@ -469,21 +469,15 @@ static void mx2_camera_clock_stop(struct soc_camera_host *ici) * Videobuf operations */ static int mx2_videobuf_setup(struct vb2_queue *vq, - const void *parg, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct soc_camera_device *icd = soc_camera_from_vb2q(vq); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx2_camera_dev *pcdev = ici->priv; dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]); - /* TODO: support for VIDIOC_CREATE_BUFS not ready */ - if (fmt != NULL) - return -ENOTTY; - alloc_ctxs[0] = pcdev->alloc_ctx; sizes[0] = icd->sizeimage; @@ -1351,7 +1345,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, vb2_get_plane_payload(vb, 0)); list_del_init(&buf->internal.queue); - v4l2_get_timestamp(&vbuf->timestamp); + vb->timestamp = ktime_get_ns(); vbuf->sequence = pcdev->frame_count; if (err) vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 49c3a257a916..169ed1150226 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c @@ -23,9 +23,9 @@ #include <media/v4l2-dev.h> #include <media/videobuf2-dma-contig.h> #include <media/soc_camera.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> -#include <linux/platform_data/camera-mx3.h> +#include <linux/platform_data/media/camera-mx3.h> #include <linux/platform_data/dma-imx.h> #define MX3_CAM_DRV_NAME "mx3-camera" @@ -155,7 +155,7 @@ static void mx3_cam_dma_done(void *arg) struct mx3_camera_buffer *buf = to_mx3_vb(vb); list_del_init(&buf->queue); - v4l2_get_timestamp(&vb->timestamp); + vb->vb2_buf.timestamp = ktime_get_ns(); vb->field = mx3_cam->field; vb->sequence = mx3_cam->sequence++; vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE); @@ -185,11 +185,9 @@ static void mx3_cam_dma_done(void *arg) * Calculate the __buffer__ (not data) size and number of buffers. */ static int mx3_videobuf_setup(struct vb2_queue *vq, - const void *parg, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct soc_camera_device *icd = soc_camera_from_vb2q(vq); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx3_camera_dev *mx3_cam = ici->priv; @@ -197,33 +195,6 @@ static int mx3_videobuf_setup(struct vb2_queue *vq, if (!mx3_cam->idmac_channel[0]) return -EINVAL; - if (fmt) { - const struct soc_camera_format_xlate *xlate = soc_camera_xlate_by_fourcc(icd, - fmt->fmt.pix.pixelformat); - unsigned int bytes_per_line; - int ret; - - if (!xlate) - return -EINVAL; - - ret = soc_mbus_bytes_per_line(fmt->fmt.pix.width, - xlate->host_fmt); - if (ret < 0) - return ret; - - bytes_per_line = max_t(u32, fmt->fmt.pix.bytesperline, ret); - - ret = soc_mbus_image_size(xlate->host_fmt, bytes_per_line, - fmt->fmt.pix.height); - if (ret < 0) - return ret; - - sizes[0] = max_t(u32, fmt->fmt.pix.sizeimage, ret); - } else { - /* Called from VIDIOC_REQBUFS or in compatibility mode */ - sizes[0] = icd->sizeimage; - } - alloc_ctxs[0] = mx3_cam->alloc_ctx; if (!vq->num_buffers) @@ -232,9 +203,14 @@ static int mx3_videobuf_setup(struct vb2_queue *vq, if (!*count) *count = 2; + /* Called from VIDIOC_REQBUFS or in compatibility mode */ + if (!*num_planes) + sizes[0] = icd->sizeimage; + else if (sizes[0] < icd->sizeimage) + return -EINVAL; + /* If *num_planes != 0, we have already verified *count. */ - if (!*num_planes && - sizes[0] * *count + mx3_cam->buf_total > MAX_VIDEO_MEM * 1024 * 1024) + if (sizes[0] * *count + mx3_cam->buf_total > MAX_VIDEO_MEM * 1024 * 1024) *count = (MAX_VIDEO_MEM * 1024 * 1024 - mx3_cam->buf_total) / sizes[0]; diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c index ba8dcd11ae0e..bd721e35474a 100644 --- a/drivers/media/platform/soc_camera/omap1_camera.c +++ b/drivers/media/platform/soc_camera/omap1_camera.c @@ -28,9 +28,9 @@ #include <linux/platform_device.h> #include <linux/slab.h> -#include <media/omap1_camera.h> +#include <linux/platform_data/media/omap1_camera.h> #include <media/soc_camera.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> #include <media/videobuf-dma-contig.h> #include <media/videobuf-dma-sg.h> diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index fcb942de0c7f..415f3bda60bf 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -33,13 +33,13 @@ #include <media/v4l2-dev.h> #include <media/videobuf-dma-sg.h> #include <media/soc_camera.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> #include <media/v4l2-of.h> #include <linux/videodev2.h> #include <mach/dma.h> -#include <linux/platform_data/camera-pxa.h> +#include <linux/platform_data/media/camera-pxa.h> #define PXA_CAM_VERSION "0.0.6" #define PXA_CAM_DRV_NAME "pxa27x-camera" diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index efe57b23fac1..b7fd695b9ed5 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -21,14 +21,13 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> -#include <linux/platform_data/camera-rcar.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/videodev2.h> #include <media/soc_camera.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> #include <media/v4l2-common.h> #include <media/v4l2-dev.h> #include <media/v4l2-device.h> @@ -138,6 +137,11 @@ #define TIMEOUT_MS 100 +#define RCAR_VIN_HSYNC_ACTIVE_LOW (1 << 0) +#define RCAR_VIN_VSYNC_ACTIVE_LOW (1 << 1) +#define RCAR_VIN_BT601 (1 << 2) +#define RCAR_VIN_BT656 (1 << 3) + enum chip_id { RCAR_GEN2, RCAR_H1, @@ -527,46 +531,14 @@ struct rcar_vin_cam { * required */ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, - const void *parg, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct soc_camera_device *icd = soc_camera_from_vb2q(vq); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct rcar_vin_priv *priv = ici->priv; - if (fmt) { - const struct soc_camera_format_xlate *xlate; - unsigned int bytes_per_line; - int ret; - - if (fmt->fmt.pix.sizeimage < icd->sizeimage) - return -EINVAL; - - xlate = soc_camera_xlate_by_fourcc(icd, - fmt->fmt.pix.pixelformat); - if (!xlate) - return -EINVAL; - ret = soc_mbus_bytes_per_line(fmt->fmt.pix.width, - xlate->host_fmt); - if (ret < 0) - return ret; - - bytes_per_line = max_t(u32, fmt->fmt.pix.bytesperline, ret); - - ret = soc_mbus_image_size(xlate->host_fmt, bytes_per_line, - fmt->fmt.pix.height); - if (ret < 0) - return ret; - - sizes[0] = max_t(u32, fmt->fmt.pix.sizeimage, ret); - } else { - /* Called from VIDIOC_REQBUFS or in compatibility mode */ - sizes[0] = icd->sizeimage; - } - alloc_ctxs[0] = priv->alloc_ctx; if (!vq->num_buffers) @@ -576,14 +548,18 @@ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, *count = 2; priv->vb_count = *count; - *num_planes = 1; - /* Number of hardware slots */ if (is_continuous_transfer(priv)) priv->nr_hw_slots = MAX_BUFFER_NUM; else priv->nr_hw_slots = 1; + if (*num_planes) + return sizes[0] < icd->sizeimage ? -EINVAL : 0; + + sizes[0] = icd->sizeimage; + *num_planes = 1; + dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]); return 0; @@ -912,7 +888,7 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) priv->queue_buf[slot]->field = priv->field; priv->queue_buf[slot]->sequence = priv->sequence++; - v4l2_get_timestamp(&priv->queue_buf[slot]->timestamp); + priv->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns(); vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf, VB2_BUF_STATE_DONE); priv->queue_buf[slot] = NULL; @@ -1853,63 +1829,43 @@ static const struct of_device_id rcar_vin_of_table[] = { MODULE_DEVICE_TABLE(of, rcar_vin_of_table); #endif -static struct platform_device_id rcar_vin_id_table[] = { - { "r8a7779-vin", RCAR_H1 }, - { "r8a7778-vin", RCAR_M1 }, - { "uPD35004-vin", RCAR_E1 }, - {}, -}; -MODULE_DEVICE_TABLE(platform, rcar_vin_id_table); - static int rcar_vin_probe(struct platform_device *pdev) { const struct of_device_id *match = NULL; struct rcar_vin_priv *priv; + struct v4l2_of_endpoint ep; + struct device_node *np; struct resource *mem; - struct rcar_vin_platform_data *pdata; unsigned int pdata_flags; int irq, ret; - if (pdev->dev.of_node) { - struct v4l2_of_endpoint ep; - struct device_node *np; + match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev); - match = of_match_device(of_match_ptr(rcar_vin_of_table), - &pdev->dev); - - np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL); - if (!np) { - dev_err(&pdev->dev, "could not find endpoint\n"); - return -EINVAL; - } + np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL); + if (!np) { + dev_err(&pdev->dev, "could not find endpoint\n"); + return -EINVAL; + } - ret = v4l2_of_parse_endpoint(np, &ep); - if (ret) { - dev_err(&pdev->dev, "could not parse endpoint\n"); - return ret; - } + ret = v4l2_of_parse_endpoint(np, &ep); + if (ret) { + dev_err(&pdev->dev, "could not parse endpoint\n"); + return ret; + } - if (ep.bus_type == V4L2_MBUS_BT656) - pdata_flags = RCAR_VIN_BT656; - else { - pdata_flags = 0; - if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) - pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW; - if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) - pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW; - } + if (ep.bus_type == V4L2_MBUS_BT656) + pdata_flags = RCAR_VIN_BT656; + else { + pdata_flags = 0; + if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) + pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW; + if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) + pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW; + } - of_node_put(np); + of_node_put(np); - dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags); - } else { - pdata = pdev->dev.platform_data; - if (!pdata || !pdata->flags) { - dev_err(&pdev->dev, "platform data not set\n"); - return -EINVAL; - } - pdata_flags = pdata->flags; - } + dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (mem == NULL) @@ -1992,7 +1948,6 @@ static struct platform_driver rcar_vin_driver = { .name = DRV_NAME, .of_match_table = of_match_ptr(rcar_vin_of_table), }, - .id_table = rcar_vin_id_table, }; module_platform_driver(rcar_vin_driver); diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 67a669d826b8..90c87f2b4ec0 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -40,11 +40,11 @@ #include <media/v4l2-common.h> #include <media/v4l2-dev.h> #include <media/soc_camera.h> -#include <media/sh_mobile_ceu.h> -#include <media/sh_mobile_csi2.h> +#include <media/drv-intf/sh_mobile_ceu.h> +#include <media/drv-intf/sh_mobile_csi2.h> #include <media/videobuf2-dma-contig.h> #include <media/v4l2-mediabus.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> #include "soc_scale_crop.h" @@ -210,43 +210,14 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) * for the current frame format if required */ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq, - const void *parg, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - if (fmt) { - const struct soc_camera_format_xlate *xlate = soc_camera_xlate_by_fourcc(icd, - fmt->fmt.pix.pixelformat); - unsigned int bytes_per_line; - int ret; - - if (!xlate) - return -EINVAL; - - ret = soc_mbus_bytes_per_line(fmt->fmt.pix.width, - xlate->host_fmt); - if (ret < 0) - return ret; - - bytes_per_line = max_t(u32, fmt->fmt.pix.bytesperline, ret); - - ret = soc_mbus_image_size(xlate->host_fmt, bytes_per_line, - fmt->fmt.pix.height); - if (ret < 0) - return ret; - - sizes[0] = max_t(u32, fmt->fmt.pix.sizeimage, ret); - } else { - /* Called from VIDIOC_REQBUFS or in compatibility mode */ - sizes[0] = icd->sizeimage; - } - alloc_ctxs[0] = pcdev->alloc_ctx; if (!vq->num_buffers) @@ -255,8 +226,14 @@ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq, if (!*count) *count = 2; + /* Called from VIDIOC_REQBUFS or in compatibility mode */ + if (!*num_planes) + sizes[0] = icd->sizeimage; + else if (sizes[0] < icd->sizeimage) + return -EINVAL; + /* If *num_planes != 0, we have already verified *count. */ - if (pcdev->video_limit && !*num_planes) { + if (pcdev->video_limit) { size_t size = PAGE_ALIGN(sizes[0]) * *count; if (size + pcdev->buf_total > pcdev->video_limit) @@ -533,7 +510,7 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) pcdev->active = NULL; ret = sh_mobile_ceu_capture(pcdev); - v4l2_get_timestamp(&vbuf->timestamp); + vbuf->vb2_buf.timestamp = ktime_get_ns(); if (!ret) { vbuf->field = pcdev->field; vbuf->sequence = pcdev->sequence++; diff --git a/drivers/media/platform/soc_camera/sh_mobile_csi2.c b/drivers/media/platform/soc_camera/sh_mobile_csi2.c index 12d3626ecf22..09b18365a4b1 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_csi2.c +++ b/drivers/media/platform/soc_camera/sh_mobile_csi2.c @@ -18,10 +18,10 @@ #include <linux/videodev2.h> #include <linux/module.h> -#include <media/sh_mobile_ceu.h> -#include <media/sh_mobile_csi2.h> +#include <media/drv-intf/sh_mobile_ceu.h> +#include <media/drv-intf/sh_mobile_csi2.h> #include <media/soc_camera.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> #include <media/v4l2-common.h> #include <media/v4l2-dev.h> #include <media/v4l2-device.h> diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index dc98122e78dc..cc84c6d6a701 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -30,7 +30,7 @@ #include <linux/vmalloc.h> #include <media/soc_camera.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> #include <media/v4l2-async.h> #include <media/v4l2-clk.h> #include <media/v4l2-common.h> @@ -1360,7 +1360,7 @@ static int soc_camera_i2c_init(struct soc_camera_device *icd, struct soc_camera_host_desc *shd = &sdesc->host_desc; struct i2c_adapter *adap; struct v4l2_subdev *subdev; - char clk_name[V4L2_SUBDEV_NAME_SIZE]; + char clk_name[V4L2_CLK_NAME_SIZE]; int ret; /* First find out how we link the main client */ @@ -1391,8 +1391,8 @@ static int soc_camera_i2c_init(struct soc_camera_device *icd, ssdd->sd_pdata.regulators = NULL; shd->board_info->platform_data = ssdd; - snprintf(clk_name, sizeof(clk_name), "%d-%04x", - shd->i2c_adapter_id, shd->board_info->addr); + v4l2_clk_name_i2c(clk_name, sizeof(clk_name), + shd->i2c_adapter_id, shd->board_info->addr); icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, icd); if (IS_ERR(icd->clk)) { @@ -1526,7 +1526,7 @@ static int scan_async_group(struct soc_camera_host *ici, struct soc_camera_async_client *sasc; struct soc_camera_device *icd; struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; - char clk_name[V4L2_SUBDEV_NAME_SIZE]; + char clk_name[V4L2_CLK_NAME_SIZE]; unsigned int i; int ret; @@ -1572,8 +1572,9 @@ static int scan_async_group(struct soc_camera_host *ici, icd->sasc = sasc; icd->parent = ici->v4l2_dev.dev; - snprintf(clk_name, sizeof(clk_name), "%d-%04x", - sasd->asd.match.i2c.adapter_id, sasd->asd.match.i2c.address); + v4l2_clk_name_i2c(clk_name, sizeof(clk_name), + sasd->asd.match.i2c.adapter_id, + sasd->asd.match.i2c.address); icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, icd); if (IS_ERR(icd->clk)) { @@ -1631,7 +1632,7 @@ static int soc_of_bind(struct soc_camera_host *ici, struct soc_camera_async_client *sasc; struct soc_of_info *info; struct i2c_client *client; - char clk_name[V4L2_SUBDEV_NAME_SIZE + 32]; + char clk_name[V4L2_CLK_NAME_SIZE]; int ret; /* allocate a new subdev and add match info to it */ @@ -1674,11 +1675,11 @@ static int soc_of_bind(struct soc_camera_host *ici, client = of_find_i2c_device_by_node(remote); if (client) - snprintf(clk_name, sizeof(clk_name), "%d-%04x", - client->adapter->nr, client->addr); + v4l2_clk_name_i2c(clk_name, sizeof(clk_name), + client->adapter->nr, client->addr); else - snprintf(clk_name, sizeof(clk_name), "of-%s", - of_node_full_name(remote)); + v4l2_clk_name_of(clk_name, sizeof(clk_name), + of_node_full_name(remote)); icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, icd); if (IS_ERR(icd->clk)) { diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c index cc8eb0758219..a51d2a42998c 100644 --- a/drivers/media/platform/soc_camera/soc_camera_platform.c +++ b/drivers/media/platform/soc_camera/soc_camera_platform.c @@ -18,7 +18,7 @@ #include <linux/videodev2.h> #include <media/v4l2-subdev.h> #include <media/soc_camera.h> -#include <media/soc_camera_platform.h> +#include <linux/platform_data/media/soc_camera_platform.h> struct soc_camera_platform_priv { struct v4l2_subdev subdev; diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c index 1dbcd426683c..e3e665e1c503 100644 --- a/drivers/media/platform/soc_camera/soc_mediabus.c +++ b/drivers/media/platform/soc_camera/soc_mediabus.c @@ -13,7 +13,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-mediabus.h> -#include <media/soc_mediabus.h> +#include <media/drv-intf/soc_mediabus.h> static const struct soc_mbus_lookup mbus_fmt[] = { { diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c index a0d267e017f6..d12a419c044a 100644 --- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c @@ -191,7 +191,7 @@ static void bdisp_job_finish(struct bdisp_ctx *ctx, int vb_state) dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); if (src_vb && dst_vb) { - dst_vb->timestamp = src_vb->timestamp; + dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; dst_vb->timecode = src_vb->timecode; dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_vb->flags |= src_vb->flags & @@ -297,7 +297,7 @@ static int bdisp_get_bufs(struct bdisp_ctx *ctx) if (ret) return ret; - dst_vb->timestamp = src_vb->timestamp; + dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; return 0; } @@ -438,11 +438,9 @@ static void bdisp_ctrls_delete(struct bdisp_ctx *ctx) } static int bdisp_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nb_buf, unsigned int *nb_planes, unsigned int sizes[], void *allocators[]) { - const struct v4l2_format *fmt = parg; struct bdisp_ctx *ctx = vb2_get_drv_priv(vq); struct bdisp_frame *frame = ctx_get_frame(ctx, vq->type); @@ -455,13 +453,13 @@ static int bdisp_queue_setup(struct vb2_queue *vq, dev_err(ctx->bdisp_dev->dev, "Invalid format\n"); return -EINVAL; } + allocators[0] = ctx->bdisp_dev->alloc_ctx; - if (fmt && fmt->fmt.pix.sizeimage < frame->sizeimage) - return -EINVAL; + if (*nb_planes) + return sizes[0] < frame->sizeimage ? -EINVAL : 0; *nb_planes = 1; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : frame->sizeimage; - allocators[0] = ctx->bdisp_dev->alloc_ctx; + sizes[0] = frame->sizeimage; return 0; } diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-common.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-common.c index 95223ab71e19..2dfbe8ab5214 100644 --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-common.c +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-common.c @@ -209,18 +209,18 @@ void c8sectpfe_tuner_unregister_frontend(struct c8sectpfe *c8sectpfe, tsin = fei->channel_data[n]; - if (tsin && tsin->frontend) { - dvb_unregister_frontend(tsin->frontend); - dvb_frontend_detach(tsin->frontend); - } + if (tsin) { + if (tsin->frontend) { + dvb_unregister_frontend(tsin->frontend); + dvb_frontend_detach(tsin->frontend); + } - if (tsin && tsin->i2c_adapter) i2c_put_adapter(tsin->i2c_adapter); - if (tsin && tsin->i2c_client) { - if (tsin->i2c_client->dev.driver->owner) + if (tsin->i2c_client) { module_put(tsin->i2c_client->dev.driver->owner); - i2c_unregister_device(tsin->i2c_client); + i2c_unregister_device(tsin->i2c_client); + } } } diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c index 8490a65ae1c6..78e3cb9a628f 100644 --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c @@ -823,7 +823,7 @@ static int c8sectpfe_probe(struct platform_device *pdev) } of_node_put(i2c_bus); - tsin->rst_gpio = of_get_named_gpio(child, "rst-gpio", 0); + tsin->rst_gpio = of_get_named_gpio(child, "reset-gpios", 0); ret = gpio_is_valid(tsin->rst_gpio); if (!ret) { diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index de24effd984f..1fa00c2cf3d7 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -1288,7 +1288,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) d_vb = ctx->dst_vb; d_vb->flags = s_vb->flags; - d_vb->timestamp = s_vb->timestamp; + d_vb->vb2_buf.timestamp = s_vb->vb2_buf.timestamp; if (s_vb->flags & V4L2_BUF_FLAG_TIMECODE) d_vb->timecode = s_vb->timecode; @@ -1796,7 +1796,6 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { * Queue operations */ static int vpe_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/platform/timblogiw.c b/drivers/media/platform/timblogiw.c index 5820e45b3a9f..113c9f3c0b3e 100644 --- a/drivers/media/platform/timblogiw.c +++ b/drivers/media/platform/timblogiw.c @@ -31,7 +31,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-device.h> #include <media/videobuf-dma-contig.h> -#include <media/timb_video.h> +#include <linux/platform_data/media/timb_video.h> #define DRIVER_NAME "timb-video" diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index 32e4ff46daf3..1254f7e4d732 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -19,7 +19,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-image-sizes.h> -#include <media/ov7670.h> +#include <media/i2c/ov7670.h> #include <media/videobuf-dma-sg.h> #include <linux/delay.h> #include <linux/dma-mapping.h> diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index e18fb9f9ed2f..418113c99801 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -235,7 +235,7 @@ static int device_process(struct vim2m_ctx *ctx, out_vb->sequence = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++; in_vb->sequence = q_data->sequence++; - out_vb->timestamp = in_vb->timestamp; + out_vb->vb2_buf.timestamp = in_vb->vb2_buf.timestamp; if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE) out_vb->timecode = in_vb->timecode; @@ -710,11 +710,9 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = { */ static int vim2m_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct vim2m_ctx *ctx = vb2_get_drv_priv(vq); struct vim2m_q_data *q_data; unsigned int size, count = *nbuffers; @@ -723,17 +721,14 @@ static int vim2m_queue_setup(struct vb2_queue *vq, size = q_data->width * q_data->height * q_data->fmt->depth >> 3; - if (fmt) { - if (fmt->fmt.pix.sizeimage < size) - return -EINVAL; - size = fmt->fmt.pix.sizeimage; - } - while (size * count > MEM2MEM_VID_MEM_LIMIT) (count)--; + *nbuffers = count; + + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; *nplanes = 1; - *nbuffers = count; sizes[0] = size; /* diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h index 55b304a705d5..751c1ba391e9 100644 --- a/drivers/media/platform/vivid/vivid-core.h +++ b/drivers/media/platform/vivid/vivid-core.h @@ -264,6 +264,7 @@ struct vivid_dev { bool vflip; bool vbi_cap_interlaced; bool loop_video; + bool reduced_fps; /* Framebuffer */ unsigned long video_pbase; @@ -285,7 +286,7 @@ struct vivid_dev { bool dqbuf_error; bool seq_wrap; bool time_wrap; - __kernel_time_t time_wrap_offset; + u64 time_wrap_offset; unsigned perc_dropped_buffers; enum vivid_signal_mode std_signal_mode; unsigned query_std_last; diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c index f41ac0b01fec..b98089c95ef5 100644 --- a/drivers/media/platform/vivid/vivid-ctrls.c +++ b/drivers/media/platform/vivid/vivid-ctrls.c @@ -78,6 +78,7 @@ #define VIVID_CID_TIME_WRAP (VIVID_CID_VIVID_BASE + 39) #define VIVID_CID_MAX_EDID_BLOCKS (VIVID_CID_VIVID_BASE + 40) #define VIVID_CID_PERCENTAGE_FILL (VIVID_CID_VIVID_BASE + 41) +#define VIVID_CID_REDUCED_FPS (VIVID_CID_VIVID_BASE + 42) #define VIVID_CID_STD_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 60) #define VIVID_CID_STANDARD (VIVID_CID_VIVID_BASE + 61) @@ -424,6 +425,10 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl) dev->sensor_vflip = ctrl->val; tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip); break; + case VIVID_CID_REDUCED_FPS: + dev->reduced_fps = ctrl->val; + vivid_update_format_cap(dev, true); + break; case VIVID_CID_HAS_CROP_CAP: dev->has_crop_cap = ctrl->val; vivid_update_format_cap(dev, true); @@ -601,6 +606,15 @@ static const struct v4l2_ctrl_config vivid_ctrl_vflip = { .step = 1, }; +static const struct v4l2_ctrl_config vivid_ctrl_reduced_fps = { + .ops = &vivid_vid_cap_ctrl_ops, + .id = VIVID_CID_REDUCED_FPS, + .name = "Reduced Framerate", + .type = V4L2_CTRL_TYPE_BOOLEAN, + .max = 1, + .step = 1, +}; + static const struct v4l2_ctrl_config vivid_ctrl_has_crop_cap = { .ops = &vivid_vid_cap_ctrl_ops, .id = VIVID_CID_HAS_CROP_CAP, @@ -940,7 +954,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = { static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl) { struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming); - struct timeval tv; + u64 rem; switch (ctrl->id) { case VIVID_CID_DQBUF_ERROR: @@ -979,8 +993,16 @@ static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl) dev->time_wrap_offset = 0; break; } - v4l2_get_timestamp(&tv); - dev->time_wrap_offset = -tv.tv_sec - 16; + /* + * We want to set the time 16 seconds before the 32 bit tv_sec + * value of struct timeval would wrap around. So first we + * calculate ktime_get_ns() % ((1 << 32) * NSEC_PER_SEC), and + * then we set the offset to ((1 << 32) - 16) * NSEC_PER_SEC). + */ + div64_u64_rem(ktime_get_ns(), + 0x100000000ULL * NSEC_PER_SEC, &rem); + dev->time_wrap_offset = + (0x100000000ULL - 16) * NSEC_PER_SEC - rem; break; } return 0; @@ -1340,11 +1362,13 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, v4l2_ctrl_handler_init(hdl_vid_cap, 55); v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL); v4l2_ctrl_handler_init(hdl_vid_out, 26); - v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL); + if (!no_error_inj) + v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL); v4l2_ctrl_handler_init(hdl_vbi_cap, 21); v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL); v4l2_ctrl_handler_init(hdl_vbi_out, 19); - v4l2_ctrl_new_custom(hdl_vbi_out, &vivid_ctrl_class, NULL); + if (!no_error_inj) + v4l2_ctrl_new_custom(hdl_vbi_out, &vivid_ctrl_class, NULL); v4l2_ctrl_handler_init(hdl_radio_rx, 17); v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL); v4l2_ctrl_handler_init(hdl_radio_tx, 17); @@ -1414,6 +1438,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vflip, NULL); v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_sav, NULL); v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_eav, NULL); + v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_reduced_fps, NULL); if (show_ccs_cap) { dev->ctrl_has_crop_cap = v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_has_crop_cap, NULL); diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c index 83cc6d3b4784..9034281944a4 100644 --- a/drivers/media/platform/vivid/vivid-kthread-cap.c +++ b/drivers/media/platform/vivid/vivid-kthread-cap.c @@ -441,7 +441,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) * "Start of Exposure". */ if (dev->tstamp_src_is_soe) - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); if (dev->field_cap == V4L2_FIELD_ALTERNATE) { /* * 60 Hz standards start with the bottom field, 50 Hz standards @@ -558,8 +558,8 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) * the timestamp now. */ if (!dev->tstamp_src_is_soe) - v4l2_get_timestamp(&buf->vb.timestamp); - buf->vb.timestamp.tv_sec += dev->time_wrap_offset; + buf->vb.vb2_buf.timestamp = ktime_get_ns(); + buf->vb.vb2_buf.timestamp += dev->time_wrap_offset; } /* diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c index c2c46dcdbe95..98eed5889bc1 100644 --- a/drivers/media/platform/vivid/vivid-kthread-out.c +++ b/drivers/media/platform/vivid/vivid-kthread-out.c @@ -95,8 +95,8 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev) */ vid_out_buf->vb.sequence /= 2; } - v4l2_get_timestamp(&vid_out_buf->vb.timestamp); - vid_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset; + vid_out_buf->vb.vb2_buf.timestamp = + ktime_get_ns() + dev->time_wrap_offset; vb2_buffer_done(&vid_out_buf->vb.vb2_buf, dev->dqbuf_error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); dprintk(dev, 2, "vid_out buffer %d done\n", @@ -108,8 +108,8 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev) vivid_sliced_vbi_out_process(dev, vbi_out_buf); vbi_out_buf->vb.sequence = dev->vbi_out_seq_count; - v4l2_get_timestamp(&vbi_out_buf->vb.timestamp); - vbi_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset; + vbi_out_buf->vb.vb2_buf.timestamp = + ktime_get_ns() + dev->time_wrap_offset; vb2_buffer_done(&vbi_out_buf->vb.vb2_buf, dev->dqbuf_error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); dprintk(dev, 2, "vbi_out buffer %d done\n", diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c index 082c401764ce..3d1604cb982f 100644 --- a/drivers/media/platform/vivid/vivid-sdr-cap.c +++ b/drivers/media/platform/vivid/vivid-sdr-cap.c @@ -117,8 +117,8 @@ static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev) if (sdr_cap_buf) { sdr_cap_buf->vb.sequence = dev->sdr_cap_seq_count; vivid_sdr_cap_process(dev, sdr_cap_buf); - v4l2_get_timestamp(&sdr_cap_buf->vb.timestamp); - sdr_cap_buf->vb.timestamp.tv_sec += dev->time_wrap_offset; + sdr_cap_buf->vb.vb2_buf.timestamp = + ktime_get_ns() + dev->time_wrap_offset; vb2_buffer_done(&sdr_cap_buf->vb.vb2_buf, dev->dqbuf_error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); dev->dqbuf_error = false; @@ -213,7 +213,7 @@ static int vivid_thread_sdr_cap(void *data) return 0; } -static int sdr_cap_queue_setup(struct vb2_queue *vq, const void *parg, +static int sdr_cap_queue_setup(struct vb2_queue *vq, unsigned *nbuffers, unsigned *nplanes, unsigned sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c index e903d023e9df..cda45a582bfe 100644 --- a/drivers/media/platform/vivid/vivid-vbi-cap.c +++ b/drivers/media/platform/vivid/vivid-vbi-cap.c @@ -108,8 +108,7 @@ void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf) if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode)) vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf); - v4l2_get_timestamp(&buf->vb.timestamp); - buf->vb.timestamp.tv_sec += dev->time_wrap_offset; + buf->vb.vb2_buf.timestamp = ktime_get_ns() + dev->time_wrap_offset; } @@ -133,11 +132,10 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, vbuf[i] = dev->vbi_gen.data[i]; } - v4l2_get_timestamp(&buf->vb.timestamp); - buf->vb.timestamp.tv_sec += dev->time_wrap_offset; + buf->vb.vb2_buf.timestamp = ktime_get_ns() + dev->time_wrap_offset; } -static int vbi_cap_queue_setup(struct vb2_queue *vq, const void *parg, +static int vbi_cap_queue_setup(struct vb2_queue *vq, unsigned *nbuffers, unsigned *nplanes, unsigned sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/platform/vivid/vivid-vbi-out.c b/drivers/media/platform/vivid/vivid-vbi-out.c index 75c5709f938e..3c5a469e6f49 100644 --- a/drivers/media/platform/vivid/vivid-vbi-out.c +++ b/drivers/media/platform/vivid/vivid-vbi-out.c @@ -27,7 +27,7 @@ #include "vivid-vbi-out.h" #include "vivid-vbi-cap.h" -static int vbi_out_queue_setup(struct vb2_queue *vq, const void *parg, +static int vbi_out_queue_setup(struct vb2_queue *vq, unsigned *nbuffers, unsigned *nplanes, unsigned sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c index ef5412311b2f..b84f081c1b92 100644 --- a/drivers/media/platform/vivid/vivid-vid-cap.c +++ b/drivers/media/platform/vivid/vivid-vid-cap.c @@ -95,11 +95,10 @@ static const struct v4l2_discrete_probe webcam_probe = { VIVID_WEBCAM_SIZES }; -static int vid_cap_queue_setup(struct vb2_queue *vq, const void *parg, +static int vid_cap_queue_setup(struct vb2_queue *vq, unsigned *nbuffers, unsigned *nplanes, unsigned sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct vivid_dev *dev = vb2_get_drv_priv(vq); unsigned buffers = tpg_g_buffers(&dev->tpg); unsigned h = dev->fmt_cap_rect.height; @@ -122,27 +121,16 @@ static int vid_cap_queue_setup(struct vb2_queue *vq, const void *parg, dev->queue_setup_error = false; return -EINVAL; } - if (fmt) { - const struct v4l2_pix_format_mplane *mp; - struct v4l2_format mp_fmt; - const struct vivid_fmt *vfmt; - - if (!V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { - fmt_sp2mp(fmt, &mp_fmt); - fmt = &mp_fmt; - } - mp = &fmt->fmt.pix_mp; + if (*nplanes) { /* - * Check if the number of planes in the specified format match + * Check if the number of requested planes match * the number of buffers in the current format. You can't mix that. */ - if (mp->num_planes != buffers) + if (*nplanes != buffers) return -EINVAL; - vfmt = vivid_get_format(dev, mp->pixelformat); for (p = 0; p < buffers; p++) { - sizes[p] = mp->plane_fmt[p].sizeimage; if (sizes[p] < tpg_g_line_width(&dev->tpg, p) * h + - vfmt->data_offset[p]) + dev->fmt_cap->data_offset[p]) return -EINVAL; } } else { @@ -405,6 +393,7 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls) { struct v4l2_bt_timings *bt = &dev->dv_timings_cap.bt; unsigned size; + u64 pixelclock; switch (dev->input_type[dev->input]) { case WEBCAM: @@ -434,8 +423,15 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls) dev->src_rect.width = bt->width; dev->src_rect.height = bt->height; size = V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt); + if (dev->reduced_fps && can_reduce_fps(bt)) { + pixelclock = div_u64(bt->pixelclock * 1000, 1001); + bt->flags |= V4L2_DV_FL_REDUCED_FPS; + } else { + pixelclock = bt->pixelclock; + bt->flags &= ~V4L2_DV_FL_REDUCED_FPS; + } dev->timeperframe_vid_cap = (struct v4l2_fract) { - size / 100, (u32)bt->pixelclock / 100 + size / 100, (u32)pixelclock / 100 }; if (bt->interlaced) dev->field_cap = V4L2_FIELD_ALTERNATE; @@ -1662,7 +1658,7 @@ int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh, !valid_cvt_gtf_timings(timings)) return -EINVAL; - if (v4l2_match_dv_timings(timings, &dev->dv_timings_cap, 0)) + if (v4l2_match_dv_timings(timings, &dev->dv_timings_cap, 0, false)) return 0; if (vb2_is_busy(&dev->vb_vid_cap_q)) return -EBUSY; diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c index b77acb6a7013..64e4d66482c1 100644 --- a/drivers/media/platform/vivid/vivid-vid-out.c +++ b/drivers/media/platform/vivid/vivid-vid-out.c @@ -31,11 +31,10 @@ #include "vivid-kthread-out.h" #include "vivid-vid-out.h" -static int vid_out_queue_setup(struct vb2_queue *vq, const void *parg, +static int vid_out_queue_setup(struct vb2_queue *vq, unsigned *nbuffers, unsigned *nplanes, unsigned sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct vivid_dev *dev = vb2_get_drv_priv(vq); const struct vivid_fmt *vfmt = dev->fmt_out; unsigned planes = vfmt->buffers; @@ -64,26 +63,16 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const void *parg, return -EINVAL; } - if (fmt) { - const struct v4l2_pix_format_mplane *mp; - struct v4l2_format mp_fmt; - - if (!V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) { - fmt_sp2mp(fmt, &mp_fmt); - fmt = &mp_fmt; - } - mp = &fmt->fmt.pix_mp; + if (*nplanes) { /* - * Check if the number of planes in the specified format match + * Check if the number of requested planes match * the number of planes in the current format. You can't mix that. */ - if (mp->num_planes != planes) + if (*nplanes != planes) return -EINVAL; - sizes[0] = mp->plane_fmt[0].sizeimage; if (sizes[0] < size) return -EINVAL; for (p = 1; p < planes; p++) { - sizes[p] = mp->plane_fmt[p].sizeimage; if (sizes[p] < dev->bytesperline_out[p] * h) return -EINVAL; } @@ -224,6 +213,7 @@ void vivid_update_format_out(struct vivid_dev *dev) { struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt; unsigned size, p; + u64 pixelclock; switch (dev->output_type[dev->output]) { case SVID: @@ -245,8 +235,14 @@ void vivid_update_format_out(struct vivid_dev *dev) dev->sink_rect.width = bt->width; dev->sink_rect.height = bt->height; size = V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt); + + if (can_reduce_fps(bt) && (bt->flags & V4L2_DV_FL_REDUCED_FPS)) + pixelclock = div_u64(bt->pixelclock * 1000, 1001); + else + pixelclock = bt->pixelclock; + dev->timeperframe_vid_out = (struct v4l2_fract) { - size / 100, (u32)bt->pixelclock / 100 + size / 100, (u32)pixelclock / 100 }; if (bt->interlaced) dev->field_out = V4L2_FIELD_ALTERNATE; @@ -1149,7 +1145,7 @@ int vivid_vid_out_s_dv_timings(struct file *file, void *_fh, 0, NULL, NULL) && !valid_cvt_gtf_timings(timings)) return -EINVAL; - if (v4l2_match_dv_timings(timings, &dev->dv_timings_out, 0)) + if (v4l2_match_dv_timings(timings, &dev->dv_timings_out, 0, true)) return 0; if (vb2_is_busy(&dev->vb_vid_out_q)) return -EBUSY; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 5ce88e1f5d71..45eb65fa23db 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -274,35 +274,6 @@ static int __vsp1_video_try_format(struct vsp1_video *video, return 0; } -static bool -vsp1_video_format_adjust(struct vsp1_video *video, - const struct v4l2_pix_format_mplane *format, - struct v4l2_pix_format_mplane *adjust) -{ - unsigned int i; - - *adjust = *format; - __vsp1_video_try_format(video, adjust, NULL); - - if (format->width != adjust->width || - format->height != adjust->height || - format->pixelformat != adjust->pixelformat || - format->num_planes != adjust->num_planes) - return false; - - for (i = 0; i < format->num_planes; ++i) { - if (format->plane_fmt[i].bytesperline != - adjust->plane_fmt[i].bytesperline) - return false; - - adjust->plane_fmt[i].sizeimage = - max(adjust->plane_fmt[i].sizeimage, - format->plane_fmt[i].sizeimage); - } - - return true; -} - /* ----------------------------------------------------------------------------- * Pipeline Management */ @@ -611,7 +582,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video) spin_unlock_irqrestore(&video->irqlock, flags); done->buf.sequence = video->sequence++; - v4l2_get_timestamp(&done->buf.timestamp); + done->buf.vb2_buf.timestamp = ktime_get_ns(); for (i = 0; i < done->buf.vb2_buf.num_planes; ++i) vb2_set_plane_payload(&done->buf.vb2_buf, i, done->length[i]); vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE); @@ -787,26 +758,24 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1) */ static int -vsp1_video_queue_setup(struct vb2_queue *vq, const void *parg, +vsp1_video_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct vsp1_video *video = vb2_get_drv_priv(vq); - const struct v4l2_pix_format_mplane *format; - struct v4l2_pix_format_mplane pix_mp; + const struct v4l2_pix_format_mplane *format = &video->format; unsigned int i; - if (fmt) { - /* Make sure the format is valid and adjust the sizeimage field - * if needed. - */ - if (!vsp1_video_format_adjust(video, &fmt->fmt.pix_mp, &pix_mp)) + if (*nplanes) { + if (*nplanes != format->num_planes) return -EINVAL; - format = &pix_mp; - } else { - format = &video->format; + for (i = 0; i < *nplanes; i++) { + if (sizes[i] < format->plane_fmt[i].sizeimage) + return -EINVAL; + alloc_ctxs[i] = video->alloc_ctx; + } + return 0; } *nplanes = format->num_planes; diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c index d11cc7072cd5..722758f33924 100644 --- a/drivers/media/platform/xilinx/xilinx-dma.c +++ b/drivers/media/platform/xilinx/xilinx-dma.c @@ -303,27 +303,25 @@ static void xvip_dma_complete(void *param) buf->buf.field = V4L2_FIELD_NONE; buf->buf.sequence = dma->sequence++; - v4l2_get_timestamp(&buf->buf.timestamp); + buf->buf.vb2_buf.timestamp = ktime_get_ns(); vb2_set_plane_payload(&buf->buf.vb2_buf, 0, dma->format.sizeimage); vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE); } static int -xvip_dma_queue_setup(struct vb2_queue *vq, const void *parg, +xvip_dma_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct xvip_dma *dma = vb2_get_drv_priv(vq); + alloc_ctxs[0] = dma->alloc_ctx; /* Make sure the image size is large enough. */ - if (fmt && fmt->fmt.pix.sizeimage < dma->format.sizeimage) - return -EINVAL; + if (*nplanes) + return sizes[0] < dma->format.sizeimage ? -EINVAL : 0; *nplanes = 1; - - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : dma->format.sizeimage; - alloc_ctxs[0] = dma->alloc_ctx; + sizes[0] = dma->format.sizeimage; return 0; } diff --git a/drivers/media/platform/xilinx/xilinx-tpg.c b/drivers/media/platform/xilinx/xilinx-tpg.c index b5f7d5ecb7f6..8bd7e3736019 100644 --- a/drivers/media/platform/xilinx/xilinx-tpg.c +++ b/drivers/media/platform/xilinx/xilinx-tpg.c @@ -731,6 +731,7 @@ static int xtpg_parse_of(struct xtpg_device *xtpg) format = xvip_of_get_format(port); if (IS_ERR(format)) { dev_err(dev, "invalid format in DT"); + of_node_put(port); return PTR_ERR(format); } @@ -739,6 +740,7 @@ static int xtpg_parse_of(struct xtpg_device *xtpg) xtpg->vip_format = format; } else if (xtpg->vip_format != format) { dev_err(dev, "in/out format mismatch in DT"); + of_node_put(port); return -EINVAL; } diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index 7b7cb9c28d2c..b9bf24fefa5a 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -476,8 +476,10 @@ static int xvip_graph_dma_init(struct xvip_composite_device *xdev) for_each_child_of_node(ports, port) { ret = xvip_graph_dma_init_one(xdev, port); - if (ret < 0) + if (ret < 0) { + of_node_put(port); return ret; + } } return 0; diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 5236035f0f2a..70fd8e80198a 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -42,7 +42,7 @@ #include <linux/videodev2.h> #include <linux/io.h> #include <linux/slab.h> -#include <media/tea575x.h> +#include <media/drv-intf/tea575x.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-fh.h> @@ -108,7 +108,7 @@ static void maxiradio_tea575x_set_direction(struct snd_tea575x *tea, bool output { } -static struct snd_tea575x_ops maxiradio_tea_ops = { +static const struct snd_tea575x_ops maxiradio_tea_ops = { .set_pins = maxiradio_tea575x_set_pins, .get_pins = maxiradio_tea575x_get_pins, .set_direction = maxiradio_tea575x_set_direction, diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index b8d61cbc18cb..dc81d422b394 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -14,7 +14,7 @@ #include <linux/io.h> /* outb, outb_p */ #include <linux/isa.h> #include <linux/pnp.h> -#include <media/tea575x.h> +#include <media/drv-intf/tea575x.h> MODULE_AUTHOR("Ondrej Zary"); MODULE_DESCRIPTION("MediaForte SF16-FMR2 and SF16-FMD2 FM radio card driver"); @@ -82,7 +82,7 @@ static void fmr2_tea575x_set_direction(struct snd_tea575x *tea, bool output) { } -static struct snd_tea575x_ops fmr2_tea_ops = { +static const struct snd_tea575x_ops fmr2_tea_ops = { .set_pins = fmr2_tea575x_set_pins, .get_pins = fmr2_tea575x_get_pins, .set_direction = fmr2_tea575x_set_direction, diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 050b3bb96fec..85667a95f003 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -33,7 +33,7 @@ #include <linux/usb.h> #include <linux/workqueue.h> #include <media/v4l2-device.h> -#include <media/tea575x.h> +#include <media/drv-intf/tea575x.h> #if defined(CONFIG_LEDS_CLASS) || \ (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) @@ -150,7 +150,7 @@ static u32 shark_read_val(struct snd_tea575x *tea) return val; } -static struct snd_tea575x_ops shark_tea_ops = { +static const struct snd_tea575x_ops shark_tea_ops = { .write_val = shark_write_val, .read_val = shark_read_val, }; diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index 8654e0dc5c95..0e65a85d52c6 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -137,7 +137,7 @@ static int shark_read_reg(struct radio_tea5777 *tea, u32 *reg_ret) return 0; } -static struct radio_tea5777_ops shark_tea_ops = { +static const struct radio_tea5777_ops shark_tea_ops = { .write_reg = shark_write_reg, .read_reg = shark_read_reg, }; diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 9cbb8cdf0ac0..859f0c08ee05 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -31,7 +31,7 @@ #include <media/v4l2-event.h> #include <media/v4l2-device.h> -#include <media/si476x.h> +#include <media/drv-intf/si476x.h> #include <linux/mfd/si476x-core.h> #define FM_FREQ_RANGE_LOW 64000000 diff --git a/drivers/media/radio/radio-tea5777.h b/drivers/media/radio/radio-tea5777.h index 4ea43a90a151..4bd942526a1b 100644 --- a/drivers/media/radio/radio-tea5777.h +++ b/drivers/media/radio/radio-tea5777.h @@ -76,7 +76,7 @@ struct radio_tea5777 { u32 read_reg; u64 write_reg; struct mutex mutex; - struct radio_tea5777_ops *ops; + const struct radio_tea5777_ops *ops; void *private_data; u8 card[32]; u8 bus_info[32]; diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index 04baafe5e901..a82eb9678d6c 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -26,7 +26,7 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/module.h> -#include <media/timb_radio.h> +#include <linux/platform_data/media/timb_radio.h> #define DRIVER_NAME "timb-radio" diff --git a/drivers/media/radio/si4713/radio-usb-si4713.c b/drivers/media/radio/si4713/radio-usb-si4713.c index a77319dcba05..5146be2a1a50 100644 --- a/drivers/media/radio/si4713/radio-usb-si4713.c +++ b/drivers/media/radio/si4713/radio-usb-si4713.c @@ -31,7 +31,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/si4713.h> +#include <linux/platform_data/media/si4713.h> #include "si4713.h" diff --git a/drivers/media/radio/si4713/si4713.h b/drivers/media/radio/si4713/si4713.h index 8a376e142188..29d0e1f104d2 100644 --- a/drivers/media/radio/si4713/si4713.h +++ b/drivers/media/radio/si4713/si4713.h @@ -20,7 +20,7 @@ #include <linux/gpio/consumer.h> #include <media/v4l2-subdev.h> #include <media/v4l2-ctrls.h> -#include <media/si4713.h> +#include <linux/platform_data/media/si4713.h> #define SI4713_PRODUCT_NUMBER 0x0D diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c index 43d1ea53cb66..3e08475af579 100644 --- a/drivers/media/radio/tea575x.c +++ b/drivers/media/radio/tea575x.c @@ -31,7 +31,7 @@ #include <media/v4l2-fh.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/tea575x.h> +#include <media/drv-intf/tea575x.h> MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index b6e13116c6f5..bd4d68500085 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -101,7 +101,8 @@ config IR_SHARP_DECODER ---help--- Enable this option if you have an infrared remote control which - uses the Sharp protocol, and you need software decoding support. + uses the Sharp protocol (Sharp, Denon), and you need software + decoding support. config IR_MCE_KBD_DECODER tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol" diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 7dbc9ca6d885..5b63b1f15cb1 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -21,7 +21,7 @@ #include <linux/platform_device.h> #include <linux/irq.h> #include <media/rc-core.h> -#include <media/gpio-ir-recv.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" @@ -30,6 +30,7 @@ struct gpio_rc_dev { struct rc_dev *rcdev; int gpio_nr; bool active_low; + struct timer_list flush_timer; }; #ifdef CONFIG_OF @@ -93,12 +94,26 @@ static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) if (rc < 0) goto err_get_value; + mod_timer(&gpio_dev->flush_timer, + jiffies + nsecs_to_jiffies(gpio_dev->rcdev->timeout)); + ir_raw_event_handle(gpio_dev->rcdev); err_get_value: return IRQ_HANDLED; } +static void flush_timer(unsigned long arg) +{ + struct gpio_rc_dev *gpio_dev = (struct gpio_rc_dev *)arg; + DEFINE_IR_RAW_EVENT(ev); + + ev.timeout = true; + ev.duration = gpio_dev->rcdev->timeout; + ir_raw_event_store(gpio_dev->rcdev, &ev); + ir_raw_event_handle(gpio_dev->rcdev); +} + static int gpio_ir_recv_probe(struct platform_device *pdev) { struct gpio_rc_dev *gpio_dev; @@ -144,6 +159,9 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) rcdev->input_id.version = 0x0100; rcdev->dev.parent = &pdev->dev; rcdev->driver_name = GPIO_IR_DRIVER_NAME; + rcdev->min_timeout = 0; + rcdev->timeout = IR_DEFAULT_TIMEOUT; + rcdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT; if (pdata->allowed_protos) rcdev->allowed_protocols = pdata->allowed_protos; else @@ -154,6 +172,9 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) gpio_dev->gpio_nr = pdata->gpio_nr; gpio_dev->active_low = pdata->active_low; + setup_timer(&gpio_dev->flush_timer, flush_timer, + (unsigned long)gpio_dev); + rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv"); if (rc < 0) goto err_gpio_request; @@ -196,6 +217,7 @@ 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); + del_timer_sync(&gpio_dev->flush_timer); rc_unregister_device(gpio_dev->rcdev); gpio_free(gpio_dev->gpio_nr); kfree(gpio_dev); diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c index 30bcf188d377..182402f7b4d1 100644 --- a/drivers/media/rc/ir-jvc-decoder.c +++ b/drivers/media/rc/ir-jvc-decoder.c @@ -47,9 +47,6 @@ static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev) { struct jvc_dec *data = &dev->raw->jvc; - if (!(dev->enabled_protocols & RC_BIT_JVC)) - return 0; - if (!is_timing_event(ev)) { if (ev.reset) data->state = STATE_INACTIVE; diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index a32659fcd266..5effc65d2947 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -415,6 +415,7 @@ static int ir_lirc_unregister(struct rc_dev *dev) lirc_unregister_driver(lirc->drv->minor); lirc_buffer_free(lirc->drv->rbuf); + kfree(lirc->drv->rbuf); kfree(lirc->drv); return 0; diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c index 9f3c9b59f30c..d80986251ee0 100644 --- a/drivers/media/rc/ir-mce_kbd-decoder.c +++ b/drivers/media/rc/ir-mce_kbd-decoder.c @@ -216,9 +216,6 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev) u32 scancode; unsigned long delay; - if (!(dev->enabled_protocols & RC_BIT_MCE_KBD)) - return 0; - if (!is_timing_event(ev)) { if (ev.reset) data->state = STATE_INACTIVE; diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c index 7b81fec0820f..bea0d1eedee0 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -52,9 +52,6 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) u8 address, not_address, command, not_command; bool send_32bits = false; - if (!(dev->enabled_protocols & RC_BIT_NEC)) - return 0; - if (!is_timing_event(ev)) { if (ev.reset) data->state = STATE_INACTIVE; diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c index 84fa6e9b59a1..6ffe776abf6b 100644 --- a/drivers/media/rc/ir-rc5-decoder.c +++ b/drivers/media/rc/ir-rc5-decoder.c @@ -53,9 +53,6 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev) u32 scancode; enum rc_type protocol; - if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ))) - return 0; - if (!is_timing_event(ev)) { if (ev.reset) data->state = STATE_INACTIVE; diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c index d16bc67af732..e0e2edefa651 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -90,11 +90,6 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev) u8 toggle; enum rc_type protocol; - if (!(dev->enabled_protocols & - (RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | - RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE))) - return 0; - if (!is_timing_event(ev)) { if (ev.reset) data->state = STATE_INACTIVE; diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c index b1e19a26208d..4e1711a40466 100644 --- a/drivers/media/rc/ir-rx51.c +++ b/drivers/media/rc/ir-rx51.c @@ -31,7 +31,7 @@ #include <media/lirc.h> #include <media/lirc_dev.h> -#include <media/ir-rx51.h> +#include <linux/platform_data/media/ir-rx51.h> #define LIRC_RX51_DRIVER_FEATURES (LIRC_CAN_SET_SEND_DUTY_CYCLE | \ LIRC_CAN_SET_SEND_CARRIER | \ diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c index ad1dc6ae21fc..7331e5e7c497 100644 --- a/drivers/media/rc/ir-sanyo-decoder.c +++ b/drivers/media/rc/ir-sanyo-decoder.c @@ -58,9 +58,6 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev) u32 scancode; u8 address, command, not_command; - if (!(dev->enabled_protocols & RC_BIT_SANYO)) - return 0; - if (!is_timing_event(ev)) { if (ev.reset) { IR_dprintk(1, "SANYO event reset received. reset to state 0\n"); diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c index b7acdbae8159..317677f06f2c 100644 --- a/drivers/media/rc/ir-sharp-decoder.c +++ b/drivers/media/rc/ir-sharp-decoder.c @@ -48,9 +48,6 @@ static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev) struct sharp_dec *data = &dev->raw->sharp; u32 msg, echo, address, command, scancode; - if (!(dev->enabled_protocols & RC_BIT_SHARP)) - return 0; - if (!is_timing_event(ev)) { if (ev.reset) data->state = STATE_INACTIVE; @@ -118,7 +115,9 @@ static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev) if (data->count == SHARP_NBITS) { /* exp,chk bits should be 1,0 */ - if ((data->bits & 0x3) != 0x2) + if ((data->bits & 0x3) != 0x2 && + /* DENON variant, both chk bits 0 */ + (data->bits & 0x3) != 0x0) break; data->state = STATE_ECHO_SPACE; } else { diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c index 58ef06f35175..baa972c76e0e 100644 --- a/drivers/media/rc/ir-sony-decoder.c +++ b/drivers/media/rc/ir-sony-decoder.c @@ -46,10 +46,6 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev) u32 scancode; u8 device, subdevice, function; - if (!(dev->enabled_protocols & - (RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20))) - return 0; - if (!is_timing_event(ev)) { if (ev.reset) data->state = STATE_INACTIVE; diff --git a/drivers/media/rc/ir-xmp-decoder.c b/drivers/media/rc/ir-xmp-decoder.c index 1017d4816e8d..18596190bbb8 100644 --- a/drivers/media/rc/ir-xmp-decoder.c +++ b/drivers/media/rc/ir-xmp-decoder.c @@ -43,9 +43,6 @@ static int ir_xmp_decode(struct rc_dev *dev, struct ir_raw_event ev) { struct xmp_dec *data = &dev->raw->xmp; - if (!(dev->enabled_protocols & RC_BIT_XMP)) - return 0; - if (!is_timing_event(ev)) { if (ev.reset) data->state = STATE_INACTIVE; diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 85af7a869167..18adf580f502 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -39,6 +39,18 @@ #include "nuvoton-cir.h" +static const struct nvt_chip nvt_chips[] = { + { "w83667hg", NVT_W83667HG }, + { "NCT6775F", NVT_6775F }, + { "NCT6776F", NVT_6776F }, + { "NCT6779D", NVT_6779D }, +}; + +static inline bool is_w83667hg(struct nvt_dev *nvt) +{ + return nvt->chip_ver == NVT_W83667HG; +} + /* write val to config reg */ static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) { @@ -224,74 +236,60 @@ static void cir_wake_dump_regs(struct nvt_dev *nvt) pr_cont("\n"); } +static inline const char *nvt_find_chip(struct nvt_dev *nvt, int id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(nvt_chips); i++) + if ((id & SIO_ID_MASK) == nvt_chips[i].chip_ver) { + nvt->chip_ver = nvt_chips[i].chip_ver; + return nvt_chips[i].name; + } + + return NULL; +} + + /* detect hardware features */ -static int nvt_hw_detect(struct nvt_dev *nvt) +static void nvt_hw_detect(struct nvt_dev *nvt) { - unsigned long flags; - u8 chip_major, chip_minor; - char chip_id[12]; - bool chip_unknown = false; + const char *chip_name; + int chip_id; nvt_efm_enable(nvt); /* Check if we're wired for the alternate EFER setup */ - chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); - if (chip_major == 0xff) { + nvt->chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); + if (nvt->chip_major == 0xff) { nvt->cr_efir = CR_EFIR2; nvt->cr_efdr = CR_EFDR2; nvt_efm_enable(nvt); - chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); + nvt->chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); } - chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); - - /* these are the known working chip revisions... */ - switch (chip_major) { - case CHIP_ID_HIGH_667: - strcpy(chip_id, "w83667hg\0"); - if (chip_minor != CHIP_ID_LOW_667) - chip_unknown = true; - break; - case CHIP_ID_HIGH_677B: - strcpy(chip_id, "w83677hg\0"); - if (chip_minor != CHIP_ID_LOW_677B2 && - chip_minor != CHIP_ID_LOW_677B3) - chip_unknown = true; - break; - case CHIP_ID_HIGH_677C: - strcpy(chip_id, "w83677hg-c\0"); - if (chip_minor != CHIP_ID_LOW_677C) - chip_unknown = true; - break; - default: - strcpy(chip_id, "w836x7hg\0"); - chip_unknown = true; - break; - } + nvt->chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); + + chip_id = nvt->chip_major << 8 | nvt->chip_minor; + chip_name = nvt_find_chip(nvt, chip_id); /* warn, but still let the driver load, if we don't know this chip */ - if (chip_unknown) - nvt_pr(KERN_WARNING, "%s: unknown chip, id: 0x%02x 0x%02x, " - "it may not work...", chip_id, chip_major, chip_minor); + if (!chip_name) + dev_warn(&nvt->pdev->dev, + "unknown chip, id: 0x%02x 0x%02x, it may not work...", + nvt->chip_major, nvt->chip_minor); else - nvt_dbg("%s: chip id: 0x%02x 0x%02x", - chip_id, chip_major, chip_minor); + dev_info(&nvt->pdev->dev, + "found %s or compatible: chip id: 0x%02x 0x%02x", + chip_name, nvt->chip_major, nvt->chip_minor); nvt_efm_disable(nvt); - - spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->chip_major = chip_major; - nvt->chip_minor = chip_minor; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - - return 0; } static void nvt_cir_ldev_init(struct nvt_dev *nvt) { u8 val, psreg, psmask, psval; - if (nvt->chip_major == CHIP_ID_HIGH_667) { + if (is_w83667hg(nvt)) { psreg = CR_MULTIFUNC_PIN_SEL; psmask = MULTIFUNC_PIN_SEL_MASK; psval = MULTIFUNC_ENABLE_CIR | MULTIFUNC_ENABLE_CIRWB; @@ -485,8 +483,9 @@ static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt) duration *= SAMPLE_PERIOD; if (!count || !duration) { - nvt_pr(KERN_NOTICE, "Unable to determine carrier! (c:%u, d:%u)", - count, duration); + dev_notice(&nvt->pdev->dev, + "Unable to determine carrier! (c:%u, d:%u)", + count, duration); return 0; } @@ -661,7 +660,7 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt) { - nvt_pr(KERN_WARNING, "RX FIFO overrun detected, flushing data!"); + dev_warn(&nvt->pdev->dev, "RX FIFO overrun detected, flushing data!"); nvt->pkts = 0; nvt_clear_cir_fifo(nvt); @@ -719,7 +718,7 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) static void nvt_cir_log_irqs(u8 status, u8 iren) { - nvt_pr(KERN_INFO, "IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s", + nvt_dbg("IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s", status, iren, status & CIR_IRSTS_RDR ? " RDR" : "", status & CIR_IRSTS_RTR ? " RTR" : "", @@ -779,7 +778,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) if (!status) { nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - return IRQ_RETVAL(IRQ_NONE); + return IRQ_NONE; } /* ack/clear all irq flags we've got */ @@ -790,11 +789,10 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) iren = nvt_cir_reg_read(nvt, CIR_IREN); if (!iren) { nvt_dbg_verbose("%s exiting, CIR not enabled", __func__); - return IRQ_RETVAL(IRQ_NONE); + return IRQ_NONE; } - if (debug) - nvt_cir_log_irqs(status, iren); + nvt_cir_log_irqs(status, iren); if (status & CIR_IRSTS_RTR) { /* FIXME: add code for study/learn mode */ @@ -853,7 +851,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) } nvt_dbg_verbose("%s done", __func__); - return IRQ_RETVAL(IRQ_HANDLED); + return IRQ_HANDLED; } /* Interrupt service routine for CIR Wake */ @@ -867,7 +865,7 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); if (!status) - return IRQ_RETVAL(IRQ_NONE); + return IRQ_NONE; if (status & CIR_WAKE_IRSTS_IR_PENDING) nvt_clear_cir_wake_fifo(nvt); @@ -879,7 +877,7 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); if (!iren) { nvt_dbg_wake("%s exiting, wake not enabled", __func__); - return IRQ_RETVAL(IRQ_HANDLED); + return IRQ_HANDLED; } if ((status & CIR_WAKE_IRSTS_PE) && @@ -896,7 +894,7 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) } nvt_dbg_wake("%s done", __func__); - return IRQ_RETVAL(IRQ_HANDLED); + return IRQ_HANDLED; } static void nvt_enable_cir(struct nvt_dev *nvt) @@ -974,7 +972,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) struct rc_dev *rdev; int ret = -ENOMEM; - nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL); + nvt = devm_kzalloc(&pdev->dev, sizeof(struct nvt_dev), GFP_KERNEL); if (!nvt) return ret; @@ -1026,9 +1024,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) init_waitqueue_head(&nvt->tx.queue); - ret = nvt_hw_detect(nvt); - if (ret) - goto exit_free_dev_rdev; + nvt_hw_detect(nvt); /* Initialize CIR & CIR Wake Logical Devices */ nvt_efm_enable(nvt); @@ -1074,25 +1070,26 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) ret = -EBUSY; /* now claim resources */ - if (!request_region(nvt->cir_addr, + if (!devm_request_region(&pdev->dev, nvt->cir_addr, CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) goto exit_unregister_device; - if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED, - NVT_DRIVER_NAME, (void *)nvt)) - goto exit_release_cir_addr; + if (devm_request_irq(&pdev->dev, nvt->cir_irq, nvt_cir_isr, + IRQF_SHARED, NVT_DRIVER_NAME, (void *)nvt)) + goto exit_unregister_device; - if (!request_region(nvt->cir_wake_addr, + if (!devm_request_region(&pdev->dev, nvt->cir_wake_addr, CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) - goto exit_free_irq; + goto exit_unregister_device; - if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, - NVT_DRIVER_NAME, (void *)nvt)) - goto exit_release_cir_wake_addr; + if (devm_request_irq(&pdev->dev, nvt->cir_wake_irq, + nvt_cir_wake_isr, IRQF_SHARED, + NVT_DRIVER_NAME, (void *)nvt)) + goto exit_unregister_device; device_init_wakeup(&pdev->dev, true); - nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); + dev_notice(&pdev->dev, "driver has been successfully loaded\n"); if (debug) { cir_dump_regs(nvt); cir_wake_dump_regs(nvt); @@ -1100,18 +1097,11 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) return 0; -exit_release_cir_wake_addr: - release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); -exit_free_irq: - free_irq(nvt->cir_irq, nvt); -exit_release_cir_addr: - release_region(nvt->cir_addr, CIR_IOREG_LENGTH); exit_unregister_device: rc_unregister_device(rdev); rdev = NULL; exit_free_dev_rdev: rc_free_device(rdev); - kfree(nvt); return ret; } @@ -1129,15 +1119,7 @@ static void nvt_remove(struct pnp_dev *pdev) nvt_enable_wake(nvt); spin_unlock_irqrestore(&nvt->nvt_lock, flags); - /* free resources */ - free_irq(nvt->cir_irq, nvt); - free_irq(nvt->cir_wake_irq, nvt); - release_region(nvt->cir_addr, CIR_IOREG_LENGTH); - release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); - rc_unregister_device(nvt->rdev); - - kfree(nvt); } static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index e1cf23c3875b..0ad15d34e9c9 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -35,9 +35,6 @@ static int debug; -#define nvt_pr(level, text, ...) \ - printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) - #define nvt_dbg(text, ...) \ if (debug) \ printk(KERN_DEBUG \ @@ -64,6 +61,21 @@ static int debug; #define TX_BUF_LEN 256 #define RX_BUF_LEN 32 +#define SIO_ID_MASK 0xfff0 + +enum nvt_chip_ver { + NVT_UNKNOWN = 0, + NVT_W83667HG = 0xa510, + NVT_6775F = 0xb470, + NVT_6776F = 0xc330, + NVT_6779D = 0xc560 +}; + +struct nvt_chip { + const char *name; + enum nvt_chip_ver chip_ver; +}; + struct nvt_dev { struct pnp_dev *pdev; struct rc_dev *rdev; @@ -93,6 +105,7 @@ struct nvt_dev { int cir_irq; int cir_wake_irq; + enum nvt_chip_ver chip_ver; /* hardware id */ u8 chip_major; u8 chip_minor; @@ -326,15 +339,6 @@ struct nvt_dev { #define EFER_EFM_ENABLE 0x87 #define EFER_EFM_DISABLE 0xaa -/* Chip IDs found in CR_CHIP_ID_{HI,LO} */ -#define CHIP_ID_HIGH_667 0xa5 -#define CHIP_ID_HIGH_677B 0xb4 -#define CHIP_ID_HIGH_677C 0xc3 -#define CHIP_ID_LOW_667 0x13 -#define CHIP_ID_LOW_677B2 0x72 -#define CHIP_ID_LOW_677B3 0x73 -#define CHIP_ID_LOW_677C 0x33 - /* Config regs we need to care about */ #define CR_SOFTWARE_RESET 0x02 #define CR_LOGICAL_DEV_SEL 0x07 diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index b68d4f762734..7359f3d03b64 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -167,75 +167,4 @@ void ir_raw_init(void); * loads the compiled decoders for their usage with IR raw events */ -/* from ir-nec-decoder.c */ -#ifdef CONFIG_IR_NEC_DECODER_MODULE -#define load_nec_decode() request_module_nowait("ir-nec-decoder") -#else -static inline void load_nec_decode(void) { } -#endif - -/* from ir-rc5-decoder.c */ -#ifdef CONFIG_IR_RC5_DECODER_MODULE -#define load_rc5_decode() request_module_nowait("ir-rc5-decoder") -#else -static inline void load_rc5_decode(void) { } -#endif - -/* from ir-rc6-decoder.c */ -#ifdef CONFIG_IR_RC6_DECODER_MODULE -#define load_rc6_decode() request_module_nowait("ir-rc6-decoder") -#else -static inline void load_rc6_decode(void) { } -#endif - -/* from ir-jvc-decoder.c */ -#ifdef CONFIG_IR_JVC_DECODER_MODULE -#define load_jvc_decode() request_module_nowait("ir-jvc-decoder") -#else -static inline void load_jvc_decode(void) { } -#endif - -/* from ir-sony-decoder.c */ -#ifdef CONFIG_IR_SONY_DECODER_MODULE -#define load_sony_decode() request_module_nowait("ir-sony-decoder") -#else -static inline void load_sony_decode(void) { } -#endif - -/* from ir-sanyo-decoder.c */ -#ifdef CONFIG_IR_SANYO_DECODER_MODULE -#define load_sanyo_decode() request_module_nowait("ir-sanyo-decoder") -#else -static inline void load_sanyo_decode(void) { } -#endif - -/* from ir-sharp-decoder.c */ -#ifdef CONFIG_IR_SHARP_DECODER_MODULE -#define load_sharp_decode() request_module_nowait("ir-sharp-decoder") -#else -static inline void load_sharp_decode(void) { } -#endif - -/* from ir-mce_kbd-decoder.c */ -#ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE -#define load_mce_kbd_decode() request_module_nowait("ir-mce_kbd-decoder") -#else -static inline void load_mce_kbd_decode(void) { } -#endif - -/* from ir-lirc-codec.c */ -#ifdef CONFIG_IR_LIRC_CODEC_MODULE -#define load_lirc_codec() request_module_nowait("ir-lirc-codec") -#else -static inline void load_lirc_codec(void) { } -#endif - -/* from ir-xmp-decoder.c */ -#ifdef CONFIG_IR_XMP_DECODER_MODULE -#define load_xmp_decode() request_module_nowait("ir-xmp-decoder") -#else -static inline void load_xmp_decode(void) { } -#endif - - #endif /* _RC_CORE_PRIV */ diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index ad260520a9d4..c69807fe2fef 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -59,7 +59,9 @@ static int ir_raw_event_thread(void *data) mutex_lock(&ir_raw_handler_lock); list_for_each_entry(handler, &ir_raw_handler_list, list) - handler->decode(raw->dev, ev); + if (raw->dev->enabled_protocols & handler->protocols || + !handler->protocols) + handler->decode(raw->dev, ev); raw->prev_ev = ev; mutex_unlock(&ir_raw_handler_lock); } @@ -246,6 +248,14 @@ static int change_protocol(struct rc_dev *dev, u64 *rc_type) return 0; } +static void ir_raw_disable_protocols(struct rc_dev *dev, u64 protocols) +{ + mutex_lock(&dev->lock); + dev->enabled_protocols &= ~protocols; + dev->enabled_wakeup_protocols &= ~protocols; + mutex_unlock(&dev->lock); +} + /* * Used to (un)register raw event clients */ @@ -337,33 +347,16 @@ EXPORT_SYMBOL(ir_raw_handler_register); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) { struct ir_raw_event_ctrl *raw; + u64 protocols = ir_raw_handler->protocols; mutex_lock(&ir_raw_handler_lock); list_del(&ir_raw_handler->list); - if (ir_raw_handler->raw_unregister) - list_for_each_entry(raw, &ir_raw_client_list, list) + list_for_each_entry(raw, &ir_raw_client_list, list) { + ir_raw_disable_protocols(raw->dev, protocols); + if (ir_raw_handler->raw_unregister) ir_raw_handler->raw_unregister(raw->dev); - available_protocols &= ~ir_raw_handler->protocols; + } + available_protocols &= ~protocols; mutex_unlock(&ir_raw_handler_lock); } EXPORT_SYMBOL(ir_raw_handler_unregister); - -void ir_raw_init(void) -{ - /* Load the decoder modules */ - - load_nec_decode(); - load_rc5_decode(); - load_rc6_decode(); - load_jvc_decode(); - load_sony_decode(); - load_sanyo_decode(); - load_sharp_decode(); - load_mce_kbd_decode(); - load_lirc_codec(); - load_xmp_decode(); - - /* If needed, we may later add some init code. In this case, - it is needed to change the CONFIG_MODULE test at rc-core.h - */ -} diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 3f0f71adabb4..1042fa331a07 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -61,7 +61,7 @@ struct rc_map *rc_map_get(const char *name) struct rc_map_list *map; map = seek_rc_map(name); -#ifdef MODULE +#ifdef CONFIG_MODULES if (!map) { int rc = request_module("%s", name); if (rc < 0) { @@ -777,30 +777,31 @@ static struct class rc_class = { * used by the sysfs protocols file. Note that the order * of the entries is relevant. */ -static struct { +static const struct { u64 type; - char *name; + const char *name; + const char *module_name; } proto_names[] = { - { RC_BIT_NONE, "none" }, - { RC_BIT_OTHER, "other" }, - { RC_BIT_UNKNOWN, "unknown" }, + { RC_BIT_NONE, "none", NULL }, + { RC_BIT_OTHER, "other", NULL }, + { RC_BIT_UNKNOWN, "unknown", NULL }, { RC_BIT_RC5 | - RC_BIT_RC5X, "rc-5" }, - { RC_BIT_NEC, "nec" }, + RC_BIT_RC5X, "rc-5", "ir-rc5-decoder" }, + { RC_BIT_NEC, "nec", "ir-nec-decoder" }, { RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 | - RC_BIT_RC6_MCE, "rc-6" }, - { RC_BIT_JVC, "jvc" }, + RC_BIT_RC6_MCE, "rc-6", "ir-rc6-decoder" }, + { RC_BIT_JVC, "jvc", "ir-jvc-decoder" }, { RC_BIT_SONY12 | RC_BIT_SONY15 | - RC_BIT_SONY20, "sony" }, - { RC_BIT_RC5_SZ, "rc-5-sz" }, - { RC_BIT_SANYO, "sanyo" }, - { RC_BIT_SHARP, "sharp" }, - { RC_BIT_MCE_KBD, "mce_kbd" }, - { RC_BIT_XMP, "xmp" }, + RC_BIT_SONY20, "sony", "ir-sony-decoder" }, + { RC_BIT_RC5_SZ, "rc-5-sz", "ir-rc5-decoder" }, + { RC_BIT_SANYO, "sanyo", "ir-sanyo-decoder" }, + { RC_BIT_SHARP, "sharp", "ir-sharp-decoder" }, + { RC_BIT_MCE_KBD, "mce_kbd", "ir-mce_kbd-decoder" }, + { RC_BIT_XMP, "xmp", "ir-xmp-decoder" }, }; /** @@ -979,6 +980,48 @@ static int parse_protocol_change(u64 *protocols, const char *buf) return count; } +static void ir_raw_load_modules(u64 *protocols) + +{ + u64 available; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(proto_names); i++) { + if (proto_names[i].type == RC_BIT_NONE || + proto_names[i].type & (RC_BIT_OTHER | RC_BIT_UNKNOWN)) + continue; + + available = ir_raw_get_allowed_protocols(); + if (!(*protocols & proto_names[i].type & ~available)) + continue; + + if (!proto_names[i].module_name) { + pr_err("Can't enable IR protocol %s\n", + proto_names[i].name); + *protocols &= ~proto_names[i].type; + continue; + } + + ret = request_module("%s", proto_names[i].module_name); + if (ret < 0) { + pr_err("Couldn't load IR protocol module %s\n", + proto_names[i].module_name); + *protocols &= ~proto_names[i].type; + continue; + } + msleep(20); + available = ir_raw_get_allowed_protocols(); + if (!(*protocols & proto_names[i].type & ~available)) + continue; + + pr_err("Loaded IR protocol module %s, \ + but protocol %s still not available\n", + proto_names[i].module_name, + proto_names[i].name); + *protocols &= ~proto_names[i].type; + } +} + /** * store_protocols() - changes the current/wakeup IR protocol(s) * @device: the device descriptor @@ -1045,6 +1088,9 @@ static ssize_t store_protocols(struct device *device, goto out; } + if (dev->driver_type == RC_DRIVER_IR_RAW) + ir_raw_load_modules(&new_protocols); + if (new_protocols != old_protocols) { *current_protocols = new_protocols; IR_dprintk(1, "Protocols changed to 0x%llx\n", @@ -1420,17 +1466,13 @@ int rc_register_device(struct rc_dev *dev) dev->input_dev->rep[REP_PERIOD] = 125; path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); - printk(KERN_INFO "%s: %s as %s\n", - dev_name(&dev->dev), - dev->input_name ? dev->input_name : "Unspecified device", - path ? path : "N/A"); + dev_info(&dev->dev, "%s as %s\n", + dev->input_name ?: "Unspecified device", path ?: "N/A"); kfree(path); if (dev->driver_type == RC_DRIVER_IR_RAW) { - /* Load raw decoders, if they aren't already */ if (!raw_init) { - IR_dprintk(1, "Loading raw decoders\n"); - ir_raw_init(); + request_module_nowait("ir-lirc-codec"); raw_init = true; } /* calls ir_register_device so unlock mutex here*/ diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c index 37d040158dff..1fa0c9d1c508 100644 --- a/drivers/media/rc/st_rc.c +++ b/drivers/media/rc/st_rc.c @@ -16,6 +16,7 @@ #include <linux/reset.h> #include <media/rc-core.h> #include <linux/pinctrl/consumer.h> +#include <linux/pm_wakeirq.h> struct st_rc_device { struct device *dev; @@ -190,6 +191,9 @@ static void st_rc_hardware_init(struct st_rc_device *dev) static int st_rc_remove(struct platform_device *pdev) { struct st_rc_device *rc_dev = platform_get_drvdata(pdev); + + dev_pm_clear_wake_irq(&pdev->dev); + device_init_wakeup(&pdev->dev, false); clk_disable_unprepare(rc_dev->sys_clock); rc_unregister_device(rc_dev->rdev); return 0; @@ -298,22 +302,22 @@ static int st_rc_probe(struct platform_device *pdev) rdev->map_name = RC_MAP_LIRC; rdev->input_name = "ST Remote Control Receiver"; - /* enable wake via this device */ - device_set_wakeup_capable(dev, true); - device_set_wakeup_enable(dev, true); - ret = rc_register_device(rdev); if (ret < 0) goto clkerr; rc_dev->rdev = rdev; if (devm_request_irq(dev, rc_dev->irq, st_rc_rx_interrupt, - IRQF_NO_SUSPEND, IR_ST_NAME, rc_dev) < 0) { + 0, IR_ST_NAME, rc_dev) < 0) { dev_err(dev, "IRQ %d register failed\n", rc_dev->irq); ret = -EINVAL; goto rcerr; } + /* enable wake via this device */ + 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 5a17cb88ff27..815243c65bc3 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -34,6 +34,7 @@ #include <linux/device.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/ktime.h> #include <linux/usb.h> #include <linux/usb/input.h> #include <media/rc-core.h> @@ -96,8 +97,8 @@ struct streamzap_ir { /* sum of signal lengths received since signal start */ unsigned long sum; /* start time of signal; necessary for gap tracking */ - struct timeval signal_last; - struct timeval signal_start; + ktime_t signal_last; + ktime_t signal_start; bool timeout_enabled; char name[128]; @@ -136,20 +137,18 @@ static void sz_push_full_pulse(struct streamzap_ir *sz, DEFINE_IR_RAW_EVENT(rawir); if (sz->idle) { - long deltv; + int delta; sz->signal_last = sz->signal_start; - do_gettimeofday(&sz->signal_start); + sz->signal_start = ktime_get_real(); - deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec; + delta = ktime_us_delta(sz->signal_start, sz->signal_last); rawir.pulse = false; - if (deltv > 15) { + if (delta > (15 * USEC_PER_SEC)) { /* really long time */ rawir.duration = IR_MAX_DURATION; } else { - rawir.duration = (int)(deltv * 1000000 + - sz->signal_start.tv_usec - - sz->signal_last.tv_usec); + rawir.duration = delta; rawir.duration -= sz->sum; rawir.duration = US_TO_NS(rawir.duration); rawir.duration = (rawir.duration > IR_MAX_DURATION) ? @@ -428,7 +427,7 @@ static int streamzap_probe(struct usb_interface *intf, sz->max_timeout = US_TO_NS(SZ_TIMEOUT * SZ_RESOLUTION); #endif - do_gettimeofday(&sz->signal_start); + sz->signal_start = ktime_get_real(); /* Complete final initialisations */ usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in, diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index 7830aef3db45..40f77685cc4a 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -153,6 +153,8 @@ static int sunxi_ir_probe(struct platform_device *pdev) if (!ir) return -ENOMEM; + spin_lock_init(&ir->ir_lock); + if (of_device_is_compatible(dn, "allwinner,sun5i-a13-ir")) ir->fifo_size = 64; else diff --git a/drivers/media/tuners/max2165.c b/drivers/media/tuners/max2165.c index 95ed46f2cd26..353b178becf6 100644 --- a/drivers/media/tuners/max2165.c +++ b/drivers/media/tuners/max2165.c @@ -385,7 +385,7 @@ static const struct dvb_tuner_ops max2165_tuner_ops = { .info = { .name = "Maxim MAX2165", .frequency_min = 470000000, - .frequency_max = 780000000, + .frequency_max = 862000000, .frequency_step = 50000, }, diff --git a/drivers/media/tuners/mt2063.c b/drivers/media/tuners/mt2063.c index 9e9c5eb4cb66..6457ac91ef09 100644 --- a/drivers/media/tuners/mt2063.c +++ b/drivers/media/tuners/mt2063.c @@ -225,7 +225,6 @@ struct mt2063_state { const struct mt2063_config *config; struct dvb_tuner_ops ops; struct dvb_frontend *frontend; - struct tuner_state status; u32 frequency; u32 srate; diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index ce157edd45fa..0e1ca2b00e61 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -168,6 +168,7 @@ static int si2157_init(struct dvb_frontend *fe) len = fw->data[fw->size - remaining]; if (len > SI2157_ARGLEN) { dev_err(&client->dev, "Bad firmware length\n"); + ret = -EINVAL; goto err_release_firmware; } memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c index 565a59310747..0d4ac5947f3a 100644 --- a/drivers/media/usb/airspy/airspy.c +++ b/drivers/media/usb/airspy/airspy.c @@ -316,7 +316,7 @@ static void airspy_urb_complete(struct urb *urb) len = airspy_convert_stream(s, ptr, urb->transfer_buffer, urb->actual_length); vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len); - v4l2_get_timestamp(&fbuf->vb.timestamp); + fbuf->vb.vb2_buf.timestamp = ktime_get_ns(); fbuf->vb.sequence = s->sequence++; vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); } @@ -488,7 +488,7 @@ static void airspy_disconnect(struct usb_interface *intf) /* Videobuf2 operations */ static int airspy_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, + unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { struct airspy *s = vb2_get_drv_priv(vq); diff --git a/drivers/media/usb/as102/as102_fw.c b/drivers/media/usb/as102/as102_fw.c index 07d08c49f4d4..5a28ce3a1d49 100644 --- a/drivers/media/usb/as102/as102_fw.c +++ b/drivers/media/usb/as102/as102_fw.c @@ -198,6 +198,7 @@ int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap) pr_info("%s: firmware: %s loaded with success\n", DRIVER_NAME, fw1); release_firmware(firmware); + firmware = NULL; /* wait for boot to complete */ mdelay(100); diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c index 130c8b49bf7f..b4efc103ae57 100644 --- a/drivers/media/usb/au0828/au0828-vbi.c +++ b/drivers/media/usb/au0828/au0828-vbi.c @@ -30,23 +30,17 @@ /* ------------------------------------------------------------------ */ -static int vbi_queue_setup(struct vb2_queue *vq, const void *parg, +static int vbi_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct au0828_dev *dev = vb2_get_drv_priv(vq); - unsigned long img_size = dev->vbi_width * dev->vbi_height * 2; - unsigned long size; - - size = fmt ? (fmt->fmt.vbi.samples_per_line * - (fmt->fmt.vbi.count[0] + fmt->fmt.vbi.count[1])) : img_size; - if (size < img_size) - return -EINVAL; + unsigned long size = dev->vbi_width * dev->vbi_height * 2; + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; *nplanes = 1; sizes[0] = size; - return 0; } diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 45c622e234f7..0a725a161dd6 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -314,7 +314,7 @@ static inline void buffer_filled(struct au0828_dev *dev, vb->sequence = dev->vbi_frame_count++; vb->field = V4L2_FIELD_INTERLACED; - v4l2_get_timestamp(&vb->timestamp); + vb->vb2_buf.timestamp = ktime_get_ns(); vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE); } @@ -638,19 +638,15 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) return rc; } -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct au0828_dev *dev = vb2_get_drv_priv(vq); - unsigned long img_size = dev->height * dev->bytesperline; - unsigned long size; - - size = fmt ? fmt->fmt.pix.sizeimage : img_size; - if (size < img_size) - return -EINVAL; + unsigned long size = dev->height * dev->bytesperline; + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; *nplanes = 1; sizes[0] = size; diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c index 351a78a84c3d..c1aa1ab2ece9 100644 --- a/drivers/media/usb/cpia2/cpia2_usb.c +++ b/drivers/media/usb/cpia2/cpia2_usb.c @@ -890,8 +890,7 @@ static void cpia2_usb_disconnect(struct usb_interface *intf) DBG("Wakeup waiting processes\n"); cam->curbuff->status = FRAME_READY; cam->curbuff->length = 0; - if (waitqueue_active(&cam->wq_stream)) - wake_up_interruptible(&cam->wq_stream); + wake_up_interruptible(&cam->wq_stream); } DBG("Releasing interface\n"); diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 47a98a2014a5..48643b94e694 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -37,7 +37,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/cx2341x.h> +#include <media/drv-intf/cx2341x.h> #include <media/tuner.h> #define CX231xx_FIRM_IMAGE_SIZE 376836 @@ -1492,6 +1492,27 @@ static struct videobuf_queue_ops cx231xx_qops = { /* ------------------------------------------------------------------ */ +static int vidioc_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *cc) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + bool is_50hz = dev->encodernorm.id & V4L2_STD_625_50; + + if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + cc->bounds.left = 0; + cc->bounds.top = 0; + cc->bounds.width = dev->ts1.width; + cc->bounds.height = dev->ts1.height; + cc->defrect = cc->bounds; + cc->pixelaspect.numerator = is_50hz ? 54 : 11; + cc->pixelaspect.denominator = is_50hz ? 59 : 10; + + return 0; +} + static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm) { struct cx231xx_fh *fh = file->private_data; @@ -1834,6 +1855,7 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_g_input = cx231xx_g_input, .vidioc_s_input = cx231xx_s_input, .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_cropcap = vidioc_cropcap, .vidioc_querycap = cx231xx_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, @@ -1901,7 +1923,7 @@ static int cx231xx_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx) return 0; } -static struct cx2341x_handler_ops cx231xx_ops = { +static const struct cx2341x_handler_ops cx231xx_ops = { /* needed for the video clock freq */ .s_audio_sampling_freq = cx231xx_s_audio_sampling_freq, /* needed for setting up the video resolution */ diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 4a117a58c39a..89dc695c696e 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -30,7 +30,7 @@ #include <media/tveeprom.h> #include <media/v4l2-common.h> -#include <media/cx25840.h> +#include <media/drv-intf/cx25840.h> #include "dvb-usb-ids.h" #include "xc5000.h" #include "tda18271.h" @@ -352,7 +352,7 @@ struct cx231xx_board cx231xx_boards[] = { .agc_analog_digital_select_gpio = 0x0c, .gpio_pin_status_mask = 0x4001000, .tuner_i2c_master = I2C_1_MUX_1, - .demod_i2c_master = I2C_2, + .demod_i2c_master = I2C_1_MUX_1, .has_dvb = 1, .demod_addr = 0x0e, .norm = V4L2_STD_NTSC, @@ -713,7 +713,7 @@ struct cx231xx_board cx231xx_boards[] = { .agc_analog_digital_select_gpio = 0x0c, .gpio_pin_status_mask = 0x4001000, .tuner_i2c_master = I2C_1_MUX_3, - .demod_i2c_master = I2C_2, + .demod_i2c_master = I2C_1_MUX_3, .has_dvb = 1, .demod_addr = 0x0e, .norm = V4L2_STD_PAL, @@ -752,7 +752,7 @@ struct cx231xx_board cx231xx_boards[] = { .agc_analog_digital_select_gpio = 0x0c, .gpio_pin_status_mask = 0x4001000, .tuner_i2c_master = I2C_1_MUX_3, - .demod_i2c_master = I2C_2, + .demod_i2c_master = I2C_1_MUX_3, .has_dvb = 1, .demod_addr = 0x0e, .norm = V4L2_STD_PAL, @@ -791,7 +791,7 @@ struct cx231xx_board cx231xx_boards[] = { .agc_analog_digital_select_gpio = 0x0c, .gpio_pin_status_mask = 0x4001000, .tuner_i2c_master = I2C_1_MUX_3, - .demod_i2c_master = I2C_2, + .demod_i2c_master = I2C_1_MUX_3, .has_dvb = 1, .demod_addr = 0x0e, .norm = V4L2_STD_NTSC, diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c index a2fd49b6be83..f497888d94bf 100644 --- a/drivers/media/usb/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c @@ -914,6 +914,7 @@ EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc); */ void cx231xx_uninit_bulk(struct cx231xx *dev) { + struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; struct urb *urb; int i; @@ -931,7 +932,7 @@ void cx231xx_uninit_bulk(struct cx231xx *dev) if (dev->video_mode.bulk_ctl.transfer_buffer[i]) { usb_free_coherent(dev->udev, urb->transfer_buffer_length, - dev->video_mode.isoc_ctl. + dev->video_mode.bulk_ctl. transfer_buffer[i], urb->transfer_dma); } @@ -943,10 +944,12 @@ void cx231xx_uninit_bulk(struct cx231xx *dev) kfree(dev->video_mode.bulk_ctl.urb); kfree(dev->video_mode.bulk_ctl.transfer_buffer); + kfree(dma_q->p_left_data); dev->video_mode.bulk_ctl.urb = NULL; dev->video_mode.bulk_ctl.transfer_buffer = NULL; dev->video_mode.bulk_ctl.num_bufs = 0; + dma_q->p_left_data = NULL; if (dev->mode_tv == 0) cx231xx_capture_start(dev, 0, Raw_Video); @@ -1196,6 +1199,16 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, sb_size, cx231xx_bulk_irq_callback, dma_q); } + /* clear halt */ + rc = usb_clear_halt(dev->udev, dev->video_mode.bulk_ctl.urb[0]->pipe); + if (rc < 0) { + dev_err(dev->dev, + "failed to clear USB bulk endpoint stall/halt condition (error=%i)\n", + rc); + cx231xx_uninit_bulk(dev); + return rc; + } + init_waitqueue_head(&dma_q->wq); /* submit urbs and enables IRQ */ diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index 66ee161fc7ba..e3594b9fab4a 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c @@ -725,7 +725,7 @@ static int dvb_init(struct cx231xx *dev) dev->dvb->frontend = dvb_attach(lgdt3305_attach, &hcw_lgdt3305_config, - tuner_i2c); + demod_i2c); if (dev->dvb->frontend == NULL) { dev_err(dev->dev, @@ -746,7 +746,7 @@ static int dvb_init(struct cx231xx *dev) dev->dvb->frontend = dvb_attach(si2165_attach, &hauppauge_930C_HD_1113xx_si2165_config, - tuner_i2c + demod_i2c ); if (dev->dvb->frontend == NULL) { @@ -779,7 +779,7 @@ static int dvb_init(struct cx231xx *dev) dev->dvb->frontend = dvb_attach(si2165_attach, &pctv_quatro_stick_1114xx_si2165_config, - tuner_i2c + demod_i2c ); if (dev->dvb->frontend == NULL) { @@ -835,7 +835,7 @@ static int dvb_init(struct cx231xx *dev) dev->dvb->frontend = dvb_attach(lgdt3306a_attach, &hauppauge_955q_lgdt3306a_config, - tuner_i2c + demod_i2c ); if (dev->dvb->frontend == NULL) { diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c index a08014d20a5c..15bb573b78ac 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c @@ -32,7 +32,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> -#include <media/msp3400.h> +#include <media/drv-intf/msp3400.h> #include <media/tuner.h> #include "cx231xx-vbi.h" diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index d0d8f08e37c8..a70850fe6235 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -36,7 +36,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/msp3400.h> +#include <media/drv-intf/msp3400.h> #include <media/tuner.h> #include "dvb_frontend.h" @@ -1444,6 +1444,7 @@ static int vidioc_cropcap(struct file *file, void *priv, { struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; + bool is_50hz = dev->norm & V4L2_STD_625_50; if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -1453,8 +1454,8 @@ static int vidioc_cropcap(struct file *file, void *priv, cc->bounds.width = dev->width; cc->bounds.height = dev->height; cc->defrect = cc->bounds; - cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ - cc->pixelaspect.denominator = 59; + cc->pixelaspect.numerator = is_50hz ? 54 : 11; + cc->pixelaspect.denominator = is_50hz ? 59 : 10; return 0; } diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index 54790fbe8fdc..ec6d3f5bc36d 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -30,14 +30,14 @@ #include <linux/mutex.h> #include <linux/usb.h> -#include <media/cx2341x.h> +#include <media/drv-intf/cx2341x.h> #include <media/videobuf-vmalloc.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-fh.h> #include <media/rc-core.h> -#include <media/ir-kbd-i2c.h> +#include <media/i2c/ir-kbd-i2c.h> #include <media/videobuf-dvb.h> #include "cx231xx-reg.h" diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig index 9facc92c8dea..3dc8ef004f8b 100644 --- a/drivers/media/usb/dvb-usb-v2/Kconfig +++ b/drivers/media/usb/dvb-usb-v2/Kconfig @@ -9,7 +9,7 @@ config DVB_USB_V2 <file:Documentation/dvb/README.dvb-usb>. For a complete list of supported USB devices see the LinuxTV DVB Wiki: - <http://www.linuxtv.org/wiki/index.php/DVB_USB> + <https://linuxtv.org/wiki/index.php/DVB_USB> Say Y if you own a USB DVB device. diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c index ea3753653368..84f6de6fa07d 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c @@ -35,7 +35,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); struct mxl111sf_demod_state { struct mxl111sf_state *mxl_state; - struct mxl111sf_demod_config *cfg; + const struct mxl111sf_demod_config *cfg; struct dvb_frontend fe; }; @@ -579,7 +579,7 @@ static struct dvb_frontend_ops mxl111sf_demod_ops = { }; struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state, - struct mxl111sf_demod_config *cfg) + const struct mxl111sf_demod_config *cfg) { struct mxl111sf_demod_state *state = NULL; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h index 0bd83e52669c..7065aca81252 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h @@ -35,11 +35,11 @@ struct mxl111sf_demod_config { #if IS_ENABLED(CONFIG_DVB_USB_MXL111SF) extern struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state, - struct mxl111sf_demod_config *cfg); + const struct mxl111sf_demod_config *cfg); #else static inline struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state, - struct mxl111sf_demod_config *cfg) + const struct mxl111sf_demod_config *cfg) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index bec12b0e076b..1710f9038d75 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -288,9 +288,9 @@ static int mxl111sf_adap_fe_init(struct dvb_frontend *fe) err = mxl1x1sf_set_device_mode(state, adap_state->device_mode); mxl_fail(err); - mxl111sf_enable_usb_output(state); + err = mxl111sf_enable_usb_output(state); mxl_fail(err); - mxl1x1sf_top_master_ctrl(state, 1); + err = mxl1x1sf_top_master_ctrl(state, 1); mxl_fail(err); if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) && @@ -731,7 +731,7 @@ fail: return ret; } -static struct mxl111sf_demod_config mxl_demod_config = { +static const struct mxl111sf_demod_config mxl_demod_config = { .read_reg = mxl111sf_read_reg, .write_reg = mxl111sf_write_reg, .program_regs = mxl111sf_ctrl_program_regs, diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 5a503a6bb8c5..eb5787a3191e 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -181,11 +181,17 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], goto err_mutex_unlock; } else if (msg[0].addr == 0x10) { /* method 1 - integrated demod */ - req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); - req.index = CMD_DEMOD_RD | dev->page; - req.size = msg[1].len; - req.data = &msg[1].buf[0]; - ret = rtl28xxu_ctrl_msg(d, &req); + if (msg[0].buf[0] == 0x00) { + /* return demod page from driver cache */ + msg[1].buf[0] = dev->page; + ret = 0; + } else { + req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); + req.index = CMD_DEMOD_RD | dev->page; + req.size = msg[1].len; + req.data = &msg[1].buf[0]; + ret = rtl28xxu_ctrl_msg(d, &req); + } } else if (msg[0].len < 2) { /* method 2 - old I2C */ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig index 128eee61570d..f03b0b70c901 100644 --- a/drivers/media/usb/dvb-usb/Kconfig +++ b/drivers/media/usb/dvb-usb/Kconfig @@ -9,7 +9,7 @@ config DVB_USB <file:Documentation/dvb/README.dvb-usb>. For a complete list of supported USB devices see the LinuxTV DVB Wiki: - <http://www.linuxtv.org/wiki/index.php/DVB_USB> + <https://linuxtv.org/wiki/index.php/DVB_USB> Say Y if you own a USB DVB device. diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index ed0b3a87983e..b58acd3fcd99 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -21,7 +21,7 @@ #include <linux/i2c.h> #include <media/soc_camera.h> -#include <media/mt9v011.h> +#include <media/i2c/mt9v011.h> #include <media/v4l2-clk.h> #include <media/v4l2-common.h> @@ -322,7 +322,7 @@ int em28xx_detect_sensor(struct em28xx *dev) int em28xx_init_camera(struct em28xx *dev) { - char clk_name[V4L2_SUBDEV_NAME_SIZE]; + char clk_name[V4L2_CLK_NAME_SIZE]; struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus]; struct em28xx_v4l2 *v4l2 = dev->v4l2; diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 394004607059..a1b6ef5894a6 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -30,10 +30,10 @@ #include <linux/i2c.h> #include <linux/usb.h> #include <media/tuner.h> -#include <media/msp3400.h> -#include <media/saa7115.h> -#include <media/tvp5150.h> -#include <media/tvaudio.h> +#include <media/drv-intf/msp3400.h> +#include <media/i2c/saa7115.h> +#include <media/i2c/tvp5150.h> +#include <media/i2c/tvaudio.h> #include <media/i2c-addr.h> #include <media/tveeprom.h> #include <media/v4l2-common.h> @@ -1051,8 +1051,12 @@ struct em28xx_board em28xx_boards[] = { }, [EM2870_BOARD_TERRATEC_XS_MT2060] = { .name = "Terratec Cinergy T XS (MT2060)", - .valid = EM28XX_BOARD_NOT_VALIDATED, + .xclk = EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, .tuner_type = TUNER_ABSENT, /* MT2060 */ + .has_dvb = 1, + .tuner_gpio = default_tuner_gpio, }, [EM2870_BOARD_KWORLD_350U] = { .name = "Kworld 350 U DVB-T", @@ -2368,7 +2372,7 @@ struct usb_device_id em28xx_id_table[] = { { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0043), - .driver_info = EM2870_BOARD_TERRATEC_XS }, + .driver_info = EM2870_BOARD_TERRATEC_XS_MT2060 }, { USB_DEVICE(0x0ccd, 0x008e), /* Cinergy HTC USB XS Rev. 1 */ .driver_info = EM2884_BOARD_TERRATEC_HTC_USB_XS }, { USB_DEVICE(0x0ccd, 0x00ac), /* Cinergy HTC USB XS Rev. 2 */ @@ -2471,6 +2475,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM28178_BOARD_PCTV_461E }, { USB_DEVICE(0x2013, 0x025f), .driver_info = EM28178_BOARD_PCTV_292E }, + { USB_DEVICE(0x2040, 0x0264), /* Hauppauge WinTV-soloHD */ + .driver_info = EM28178_BOARD_PCTV_292E }, { USB_DEVICE(0x0413, 0x6f07), .driver_info = EM2861_BOARD_LEADTEK_VC100 }, { USB_DEVICE(0xeb1a, 0x8179), diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 357be76c7a55..bf5c24467c65 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -38,6 +38,7 @@ #include "lgdt3305.h" #include "zl10353.h" #include "s5h1409.h" +#include "mt2060.h" #include "mt352.h" #include "mt352_priv.h" /* FIXME */ #include "tda1002x.h" @@ -815,6 +816,10 @@ static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = { .parallel_ts = 1, }; +static struct mt2060_config em28xx_mt2060_config = { + .i2c_address = 0x60, +}; + static struct qt1010_config em28xx_qt1010_config = { .i2c_address = 0x62 }; @@ -1142,6 +1147,16 @@ static int em28xx_dvb_init(struct em28xx *dev) goto out_free; } break; + case EM2870_BOARD_TERRATEC_XS_MT2060: + dvb->fe[0] = dvb_attach(zl10353_attach, + &em28xx_zl10353_no_i2c_gate_dev, + &dev->i2c_adap[dev->def_i2c_bus]); + if (dvb->fe[0] != NULL) { + dvb_attach(mt2060_attach, dvb->fe[0], + &dev->i2c_adap[dev->def_i2c_bus], + &em28xx_mt2060_config, 1220); + } + break; case EM2870_BOARD_KWORLD_355U: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_no_i2c_gate_dev, diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c index e23c285b3108..fe94c9225dd7 100644 --- a/drivers/media/usb/em28xx/em28xx-vbi.c +++ b/drivers/media/usb/em28xx/em28xx-vbi.c @@ -31,26 +31,22 @@ /* ------------------------------------------------------------------ */ -static int vbi_queue_setup(struct vb2_queue *vq, const void *parg, +static int vbi_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct em28xx *dev = vb2_get_drv_priv(vq); struct em28xx_v4l2 *v4l2 = dev->v4l2; - unsigned long size; + unsigned long size = v4l2->vbi_width * v4l2->vbi_height * 2; - if (fmt) - size = fmt->fmt.pix.sizeimage; - else - size = v4l2->vbi_width * v4l2->vbi_height * 2; - - if (0 == *nbuffers) - *nbuffers = 32; if (*nbuffers < 2) *nbuffers = 2; - if (*nbuffers > 32) - *nbuffers = 32; + + if (*nplanes) { + if (sizes[0] < size) + return -EINVAL; + size = sizes[0]; + } *nplanes = 1; sizes[0] = size; diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 6a3cf342e087..0e86ff423c49 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -43,7 +43,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> #include <media/v4l2-clk.h> -#include <media/msp3400.h> +#include <media/drv-intf/msp3400.h> #include <media/tuner.h> #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \ @@ -438,7 +438,7 @@ static inline void finish_buffer(struct em28xx *dev, buf->vb.field = V4L2_FIELD_NONE; else buf->vb.field = V4L2_FIELD_INTERLACED; - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } @@ -871,30 +871,19 @@ static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type) Videobuf2 operations ------------------------------------------------------------------*/ -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct em28xx *dev = vb2_get_drv_priv(vq); struct em28xx_v4l2 *v4l2 = dev->v4l2; - unsigned long size; - - if (fmt) - size = fmt->fmt.pix.sizeimage; - else - size = + unsigned long size = (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3; - if (size == 0) - return -EINVAL; - - if (0 == *nbuffers) - *nbuffers = 32; - + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; *nplanes = 1; sizes[0] = size; - return 0; } diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 76bf8ba372b3..8ff066c977d9 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -40,7 +40,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-fh.h> -#include <media/ir-kbd-i2c.h> +#include <media/i2c/ir-kbd-i2c.h> #include <media/rc-core.h> #include "tuner-xc2028.h" #include "xc5000.h" diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c index ae1cfa792c58..05b1126f263e 100644 --- a/drivers/media/usb/go7007/go7007-driver.c +++ b/drivers/media/usb/go7007/go7007-driver.c @@ -466,7 +466,7 @@ static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buf else go7007_set_motion_regions(go, vb, 0); - v4l2_get_timestamp(&vb->vb.timestamp); + vb->vb.vb2_buf.timestamp = ktime_get_ns(); vb_tmp = vb; spin_lock(&go->spinlock); list_del(&vb->list); diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c index 4857c467e76c..3dbf14c85c5c 100644 --- a/drivers/media/usb/go7007/go7007-usb.c +++ b/drivers/media/usb/go7007/go7007-usb.c @@ -23,9 +23,9 @@ #include <linux/usb.h> #include <linux/i2c.h> #include <asm/byteorder.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> #include <media/tuner.h> -#include <media/uda1342.h> +#include <media/i2c/uda1342.h> #include "go7007-priv.h" @@ -1289,7 +1289,7 @@ static int go7007_usb_probe(struct usb_interface *intf, /* Allocate the URBs and buffers for receiving the audio stream */ if ((board->flags & GO7007_USB_EZUSB) && - (board->flags & GO7007_BOARD_HAS_AUDIO)) { + (board->main_info.flags & GO7007_BOARD_HAS_AUDIO)) { for (i = 0; i < 8; ++i) { usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); if (usb->audio_urbs[i] == NULL) diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c index f3d187db9368..358c1c186d03 100644 --- a/drivers/media/usb/go7007/go7007-v4l2.c +++ b/drivers/media/usb/go7007/go7007-v4l2.c @@ -30,7 +30,7 @@ #include <media/v4l2-subdev.h> #include <media/v4l2-event.h> #include <media/videobuf2-vmalloc.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> #include "go7007-priv.h" @@ -369,7 +369,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, } static int go7007_queue_setup(struct vb2_queue *q, - const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c index 146071b8e116..bfff1d1c70ab 100644 --- a/drivers/media/usb/gspca/ov534.c +++ b/drivers/media/usb/gspca/ov534.c @@ -1491,8 +1491,13 @@ static void sd_set_streamparm(struct gspca_dev *gspca_dev, struct v4l2_fract *tpf = &cp->timeperframe; struct sd *sd = (struct sd *) gspca_dev; - /* Set requested framerate */ - sd->frame_rate = tpf->denominator / tpf->numerator; + if (tpf->numerator == 0 || tpf->denominator == 0) + /* Set default framerate */ + sd->frame_rate = 30; + else + /* Set requested framerate */ + sd->frame_rate = tpf->denominator / tpf->numerator; + if (gspca_dev->streaming) set_frame_rate(gspca_dev); diff --git a/drivers/media/usb/gspca/topro.c b/drivers/media/usb/gspca/topro.c index c70ff406b07a..c028a5c2438e 100644 --- a/drivers/media/usb/gspca/topro.c +++ b/drivers/media/usb/gspca/topro.c @@ -4802,7 +4802,11 @@ static void sd_set_streamparm(struct gspca_dev *gspca_dev, struct v4l2_fract *tpf = &cp->timeperframe; int fr, i; - sd->framerate = tpf->denominator / tpf->numerator; + if (tpf->numerator == 0 || tpf->denominator == 0) + sd->framerate = 30; + else + sd->framerate = tpf->denominator / tpf->numerator; + if (gspca_dev->streaming) setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure)); diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c index 0fe5cb2c260c..9e700caf0d66 100644 --- a/drivers/media/usb/hackrf/hackrf.c +++ b/drivers/media/usb/hackrf/hackrf.c @@ -526,7 +526,7 @@ static void hackrf_urb_complete_in(struct urb *urb) urb->transfer_buffer, len); vb2_set_plane_payload(&buffer->vb.vb2_buf, 0, len); buffer->vb.sequence = dev->sequence++; - v4l2_get_timestamp(&buffer->vb.timestamp); + buffer->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_DONE); exit_usb_submit_urb: usb_submit_urb(urb, GFP_ATOMIC); @@ -571,7 +571,7 @@ static void hackrf_urb_complete_out(struct urb *urb) vb2_plane_vaddr(&buffer->vb.vb2_buf, 0), len); urb->actual_length = len; buffer->vb.sequence = dev->sequence++; - v4l2_get_timestamp(&buffer->vb.timestamp); + buffer->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_DONE); exit_usb_submit_urb: usb_submit_urb(urb, GFP_ATOMIC); @@ -759,7 +759,7 @@ static void hackrf_return_all_buffers(struct vb2_queue *vq, } static int hackrf_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, + unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { struct hackrf_dev *dev = vb2_get_drv_priv(vq); diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index d8d8c0f519fc..7dee22deebf3 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -642,7 +642,7 @@ static int vidioc_s_dv_timings(struct file *file, void *_fh, if (dev->status != STATUS_IDLE) return -EBUSY; for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) - if (v4l2_match_dv_timings(timings, hdpvr_dv_timings + i, 0)) + if (v4l2_match_dv_timings(timings, hdpvr_dv_timings + i, 0, false)) break; if (i == ARRAY_SIZE(hdpvr_dv_timings)) return -EINVAL; diff --git a/drivers/media/usb/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h index a3194304182d..78e815441f95 100644 --- a/drivers/media/usb/hdpvr/hdpvr.h +++ b/drivers/media/usb/hdpvr/hdpvr.h @@ -17,7 +17,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/ir-kbd-i2c.h> +#include <media/i2c/ir-kbd-i2c.h> #define HDPVR_MAX 8 #define HDPVR_I2C_MAX_SIZE 128 diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index e06a21a4fbd9..c104315fdc17 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -616,7 +616,6 @@ static int msi2500_querycap(struct file *file, void *fh, /* Videobuf2 operations */ static int msi2500_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-audio.c b/drivers/media/usb/pvrusb2/pvrusb2-audio.c index 45276c628482..5f953d837bf1 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-audio.c @@ -23,7 +23,7 @@ #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include <linux/videodev2.h> -#include <media/msp3400.h> +#include <media/drv-intf/msp3400.h> #include <media/v4l2-common.h> diff --git a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c index 1a81aa70509b..7d675fae1846 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -32,7 +32,7 @@ #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" -#include <media/cx25840.h> +#include <media/drv-intf/cx25840.h> #include <linux/videodev2.h> #include <media/v4l2-common.h> #include <linux/errno.h> diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h index 1f9c02801cee..60141b16d731 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h @@ -39,8 +39,8 @@ #include "pvrusb2-hdw.h" #include "pvrusb2-io.h" #include <media/v4l2-device.h> -#include <media/cx2341x.h> -#include <media/ir-kbd-i2c.h> +#include <media/drv-intf/cx2341x.h> +#include <media/i2c/ir-kbd-i2c.h> #include "pvrusb2-devattr.h" /* Legal values for PVR2_CID_HSM */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c index 4baa9d632a4e..14321d0a1833 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c @@ -20,7 +20,7 @@ #include <linux/i2c.h> #include <linux/module.h> -#include <media/ir-kbd-i2c.h> +#include <media/i2c/ir-kbd-i2c.h> #include "pvrusb2-i2c-core.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index 1c5f85bf7ed4..81f788b7b242 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -628,6 +628,7 @@ static int pvr2_g_ext_ctrls(struct file *file, void *priv, struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct v4l2_ext_control *ctrl; + struct pvr2_ctrl *cptr; unsigned int idx; int val; int ret; @@ -635,8 +636,15 @@ static int pvr2_g_ext_ctrls(struct file *file, void *priv, ret = 0; for (idx = 0; idx < ctls->count; idx++) { ctrl = ctls->controls + idx; - ret = pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val); + cptr = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id); + if (cptr) { + if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL) + pvr2_ctrl_get_def(cptr, &val); + else + ret = pvr2_ctrl_get_value(cptr, &val); + } else + ret = -EINVAL; + if (ret) { ctls->error_idx = idx; return ret; @@ -658,6 +666,10 @@ static int pvr2_s_ext_ctrls(struct file *file, void *priv, unsigned int idx; int ret; + /* Default value cannot be changed */ + if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL) + return -EINVAL; + ret = 0; for (idx = 0; idx < ctls->count; idx++) { ctrl = ctls->controls + idx; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c index 139b39740534..105123ab36aa 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c @@ -35,7 +35,7 @@ #include "pvrusb2-debug.h" #include <linux/videodev2.h> #include <media/v4l2-common.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> #include <linux/errno.h> struct routing_scheme { diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index b79c36fd8cd2..086cf1c7bd7d 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -316,8 +316,7 @@ static void pwc_isoc_handler(struct urb *urb) struct pwc_frame_buf *fbuf = pdev->fill_buf; if (pdev->vsync == 1) { - v4l2_get_timestamp( - &fbuf->vb.timestamp); + fbuf->vb.vb2_buf.timestamp = ktime_get_ns(); pdev->vsync = 2; } @@ -571,7 +570,7 @@ static void pwc_video_release(struct v4l2_device *v) /***************************************************************************/ /* Videobuf2 operations */ -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index e7acb12ad21d..9acdaa3716fb 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -574,7 +574,7 @@ static void s2255_got_frame(struct s2255_vc *vc, int jpgsize) buf = list_entry(vc->buf_list.next, struct s2255_buffer, list); list_del(&buf->list); - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); buf->vb.field = vc->field; buf->vb.sequence = vc->frame_count; spin_unlock_irqrestore(&vc->qlock, flags); @@ -660,7 +660,7 @@ static void s2255_fillbuff(struct s2255_vc *vc, Videobuf operations ------------------------------------------------------------------*/ -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c index 1b6836f15370..bc029478065a 100644 --- a/drivers/media/usb/stk1160/stk1160-core.c +++ b/drivers/media/usb/stk1160/stk1160-core.c @@ -34,7 +34,7 @@ #include <linux/usb.h> #include <linux/mm.h> #include <linux/vmalloc.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> #include "stk1160.h" #include "stk1160-reg.h" diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index 0bd34f1e7fa9..77131fd614a5 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -33,7 +33,7 @@ #include <media/v4l2-event.h> #include <media/videobuf2-vmalloc.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> #include "stk1160.h" #include "stk1160-reg.h" @@ -664,7 +664,7 @@ static const struct v4l2_ioctl_ops stk1160_ioctl_ops = { /* * Videobuf2 operations */ -static int queue_setup(struct vb2_queue *vq, const void *parg, +static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index 75654e676e80..46191d5262eb 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -99,7 +99,7 @@ void stk1160_buffer_done(struct stk1160 *dev) buf->vb.sequence = dev->sequence++; buf->vb.field = V4L2_FIELD_INTERLACED; buf->vb.vb2_buf.planes[0].bytesused = buf->bytesused; - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->bytesused); vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); diff --git a/drivers/media/usb/tm6000/tm6000-cards.c b/drivers/media/usb/tm6000/tm6000-cards.c index 2e8c3afe4ec4..8902ee36bc94 100644 --- a/drivers/media/usb/tm6000/tm6000-cards.c +++ b/drivers/media/usb/tm6000/tm6000-cards.c @@ -26,7 +26,7 @@ #include <linux/slab.h> #include <media/v4l2-common.h> #include <media/tuner.h> -#include <media/tvaudio.h> +#include <media/i2c/tvaudio.h> #include <media/i2c-addr.h> #include <media/rc-map.h> diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c index a5de46f04247..4e36e24cb3a6 100644 --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c @@ -1606,7 +1606,7 @@ static int fe_send_command(struct dvb_frontend* fe, const u8 command, return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result); } -static struct ttusbdecfe_config fe_config = { +static const struct ttusbdecfe_config fe_config = { .send_command = fe_send_command }; diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index e645c9df2d94..4ebb33943f9a 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -322,7 +322,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk) buf->vb.field = V4L2_FIELD_INTERLACED; buf->vb.sequence = usbtv->sequence++; - v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); vb2_buffer_done(&buf->vb.vb2_buf, state); list_del(&buf->list); @@ -599,19 +599,18 @@ static struct v4l2_file_operations usbtv_fops = { }; static int usbtv_queue_setup(struct vb2_queue *vq, - const void *parg, unsigned int *nbuffers, + unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct usbtv *usbtv = vb2_get_drv_priv(vq); unsigned size = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32); if (vq->num_buffers + *nbuffers < 2) *nbuffers = 2 - vq->num_buffers; + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; *nplanes = 1; - if (fmt && fmt->fmt.pix.sizeimage < size) - return -EINVAL; - sizes[0] = fmt ? fmt->fmt.pix.sizeimage : size; + sizes[0] = size; return 0; } diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c index dc3b4d5155c5..1ea04e75fb36 100644 --- a/drivers/media/usb/usbvision/usbvision-core.c +++ b/drivers/media/usb/usbvision/usbvision-core.c @@ -37,7 +37,7 @@ #include <linux/videodev2.h> #include <linux/i2c.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> #include <media/v4l2-common.h> #include <media/tuner.h> diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index b693206f66dd..de9ff3bb8edd 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -59,7 +59,7 @@ #include <linux/videodev2.h> #include <linux/i2c.h> -#include <media/saa7115.h> +#include <media/i2c/saa7115.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> @@ -1461,11 +1461,32 @@ static int usbvision_probe(struct usb_interface *intf, printk(KERN_INFO "%s: %s found\n", __func__, usbvision_device_data[model].model_string); + /* + * this is a security check. + * an exploit using an incorrect bInterfaceNumber is known + */ + if (ifnum >= USB_MAXINTERFACES || !dev->actconfig->interface[ifnum]) + return -ENODEV; + if (usbvision_device_data[model].interface >= 0) interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0]; - else + else if (ifnum < dev->actconfig->desc.bNumInterfaces) interface = &dev->actconfig->interface[ifnum]->altsetting[0]; + else { + dev_err(&intf->dev, "interface %d is invalid, max is %d\n", + ifnum, dev->actconfig->desc.bNumInterfaces - 1); + ret = -ENODEV; + goto err_usb; + } + + if (interface->desc.bNumEndpoints < 2) { + dev_err(&intf->dev, "interface %d has %d endpoints, but must" + " have minimum 2\n", ifnum, interface->desc.bNumEndpoints); + ret = -ENODEV; + goto err_usb; + } endpoint = &interface->endpoint[1].desc; + if (!usb_endpoint_xfer_isoc(endpoint)) { dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n", __func__, ifnum); diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 3e59b288b8a8..c2ee6e39fd0c 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -227,7 +227,8 @@ static struct uvc_control_info uvc_ctrls[] = { .size = 4, .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, + | UVC_CTRL_FLAG_RESTORE + | UVC_CTRL_FLAG_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index d11fd6ac2df0..39abbafad796 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2540,7 +2540,8 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_FORCE_Y8 }, /* Generic USB Video Class */ - { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, + { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) }, + { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, {} }; diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index cfb868a48b5f..54394722756f 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -69,23 +69,19 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue, * videobuf2 queue operations */ -static int uvc_queue_setup(struct vb2_queue *vq, const void *parg, +static int uvc_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - const struct v4l2_format *fmt = parg; struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); + unsigned size = stream->ctrl.dwMaxVideoFrameSize; /* Make sure the image size is large enough. */ - if (fmt && fmt->fmt.pix.sizeimage < stream->ctrl.dwMaxVideoFrameSize) - return -EINVAL; - + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; *nplanes = 1; - - sizes[0] = fmt ? fmt->fmt.pix.sizeimage - : stream->ctrl.dwMaxVideoFrameSize; - + sizes[0] = size; return 0; } diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 2764f43607c1..d7723ce772b3 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -983,6 +983,22 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh, unsigned int i; int ret; + if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) { + for (i = 0; i < ctrls->count; ++ctrl, ++i) { + struct v4l2_queryctrl qc = { .id = ctrl->id }; + + ret = uvc_query_v4l2_ctrl(chain, &qc); + if (ret < 0) { + ctrls->error_idx = i; + return ret; + } + + ctrl->value = qc.default_value; + } + + return 0; + } + ret = uvc_ctrl_begin(chain); if (ret < 0) return ret; @@ -1010,6 +1026,10 @@ static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle, unsigned int i; int ret; + /* Default value cannot be changed */ + if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) + return -EINVAL; + ret = uvc_ctrl_begin(chain); if (ret < 0) return ret; diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 2b276ab7764f..075a0fe77485 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -694,22 +694,19 @@ void uvc_video_clock_update(struct uvc_streaming *stream, ts.tv_nsec -= NSEC_PER_SEC; } - uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %lu.%06lu " - "buf ts %lu.%06lu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n", + uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %llu " + "buf ts %llu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n", stream->dev->name, sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536), - y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC, - vbuf->timestamp.tv_sec, - (unsigned long)vbuf->timestamp.tv_usec, + y, timespec_to_ns(&ts), vbuf->vb2_buf.timestamp, x1, first->host_sof, first->dev_sof, x2, last->host_sof, last->dev_sof, y1, y2); /* Update the V4L2 buffer. */ - vbuf->timestamp.tv_sec = ts.tv_sec; - vbuf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; + vbuf->vb2_buf.timestamp = timespec_to_ns(&ts); done: - spin_unlock_irqrestore(&stream->clock.lock, flags); + spin_unlock_irqrestore(&clock->lock, flags); } /* ------------------------------------------------------------------------ @@ -1034,9 +1031,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, buf->buf.field = V4L2_FIELD_NONE; buf->buf.sequence = stream->sequence; - buf->buf.timestamp.tv_sec = ts.tv_sec; - buf->buf.timestamp.tv_usec = - ts.tv_nsec / NSEC_PER_USEC; + buf->buf.vb2_buf.timestamp = timespec_to_ns(&ts); /* TODO: Handle PTS and SCR. */ buf->state = UVC_BUF_STATE_ACTIVE; diff --git a/drivers/media/v4l2-core/v4l2-clk.c b/drivers/media/v4l2-core/v4l2-clk.c index 34e416a554f6..297e10e69898 100644 --- a/drivers/media/v4l2-core/v4l2-clk.c +++ b/drivers/media/v4l2-core/v4l2-clk.c @@ -15,6 +15,7 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/mutex.h> +#include <linux/of.h> #include <linux/slab.h> #include <linux/string.h> @@ -39,6 +40,7 @@ struct v4l2_clk *v4l2_clk_get(struct device *dev, const char *id) { struct v4l2_clk *clk; struct clk *ccf_clk = clk_get(dev, id); + char clk_name[V4L2_CLK_NAME_SIZE]; if (PTR_ERR(ccf_clk) == -EPROBE_DEFER) return ERR_PTR(-EPROBE_DEFER); @@ -57,6 +59,13 @@ struct v4l2_clk *v4l2_clk_get(struct device *dev, const char *id) mutex_lock(&clk_lock); clk = v4l2_clk_find(dev_name(dev)); + /* if dev_name is not found, try use the OF name to find again */ + if (PTR_ERR(clk) == -ENODEV && dev->of_node) { + v4l2_clk_name_of(clk_name, sizeof(clk_name), + of_node_full_name(dev->of_node)); + clk = v4l2_clk_find(clk_name); + } + if (!IS_ERR(clk)) atomic_inc(&clk->use_count); mutex_unlock(&clk_lock); diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 327e83ac2469..8fd84a67478a 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -630,7 +630,7 @@ static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __ } struct v4l2_ext_controls32 { - __u32 ctrl_class; + __u32 which; __u32 count; __u32 error_idx; __u32 reserved[2]; @@ -673,7 +673,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext compat_caddr_t p; if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) || - get_user(kp->ctrl_class, &up->ctrl_class) || + get_user(kp->which, &up->which) || get_user(kp->count, &up->count) || get_user(kp->error_idx, &up->error_idx) || copy_from_user(kp->reserved, up->reserved, @@ -723,7 +723,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext compat_caddr_t p; if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) || - put_user(kp->ctrl_class, &up->ctrl_class) || + put_user(kp->which, &up->which) || put_user(kp->count, &up->count) || put_user(kp->error_idx, &up->error_idx) || copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 4a1d9fdd14bb..c9d5537b6af7 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1491,6 +1491,17 @@ static int new_to_user(struct v4l2_ext_control *c, return ptr_to_user(c, ctrl, ctrl->p_new); } +/* Helper function: copy the initial control value back to the caller */ +static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) +{ + int idx; + + for (idx = 0; idx < ctrl->elems; idx++) + ctrl->type_ops->init(ctrl, idx, ctrl->p_new); + + return ptr_to_user(c, ctrl, ctrl->p_new); +} + /* Helper function: copy the caller-provider value to the given control value */ static int user_to_ptr(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl, @@ -1762,7 +1773,7 @@ static struct v4l2_ctrl_ref *find_private_ref( list_for_each_entry(ref, &hdl->ctrl_refs, node) { /* Search for private user controls that are compatible with VIDIOC_G/S_CTRL. */ - if (V4L2_CTRL_ID2CLASS(ref->ctrl->id) == V4L2_CTRL_CLASS_USER && + if (V4L2_CTRL_ID2WHICH(ref->ctrl->id) == V4L2_CTRL_CLASS_USER && V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) { if (!ref->ctrl->is_int) continue; @@ -1831,7 +1842,7 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl_ref *ref; struct v4l2_ctrl_ref *new_ref; u32 id = ctrl->id; - u32 class_ctrl = V4L2_CTRL_ID2CLASS(id) | 1; + u32 class_ctrl = V4L2_CTRL_ID2WHICH(id) | 1; int bucket = id % hdl->nr_of_buckets; /* which bucket to use */ /* @@ -2253,9 +2264,9 @@ EXPORT_SYMBOL(v4l2_ctrl_add_handler); bool v4l2_ctrl_radio_filter(const struct v4l2_ctrl *ctrl) { - if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_FM_TX) + if (V4L2_CTRL_ID2WHICH(ctrl->id) == V4L2_CTRL_CLASS_FM_TX) return true; - if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_FM_RX) + if (V4L2_CTRL_ID2WHICH(ctrl->id) == V4L2_CTRL_CLASS_FM_RX) return true; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -2710,7 +2721,9 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, cs->error_idx = i; - if (cs->ctrl_class && V4L2_CTRL_ID2CLASS(id) != cs->ctrl_class) + if (cs->which && + cs->which != V4L2_CTRL_WHICH_DEF_VAL && + V4L2_CTRL_ID2WHICH(id) != cs->which) return -EINVAL; /* Old-style private controls are not allowed for @@ -2787,11 +2800,11 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, /* Handles the corner case where cs->count == 0. It checks whether the specified control class exists. If that class ID is 0, then it checks whether there are any controls at all. */ -static int class_check(struct v4l2_ctrl_handler *hdl, u32 ctrl_class) +static int class_check(struct v4l2_ctrl_handler *hdl, u32 which) { - if (ctrl_class == 0) + if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL) return list_empty(&hdl->ctrl_refs) ? -EINVAL : 0; - return find_ref_lock(hdl, ctrl_class | 1) ? 0 : -EINVAL; + return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL; } @@ -2803,15 +2816,18 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs struct v4l2_ctrl_helper *helpers = helper; int ret; int i, j; + bool def_value; + + def_value = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); cs->error_idx = cs->count; - cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class); + cs->which = V4L2_CTRL_ID2WHICH(cs->which); if (hdl == NULL) return -EINVAL; if (cs->count == 0) - return class_check(hdl, cs->ctrl_class); + return class_check(hdl, cs->which); if (cs->count > ARRAY_SIZE(helper)) { helpers = kmalloc_array(cs->count, sizeof(helper[0]), @@ -2829,9 +2845,11 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs for (i = 0; !ret && i < cs->count; i++) { int (*ctrl_to_user)(struct v4l2_ext_control *c, - struct v4l2_ctrl *ctrl) = cur_to_user; + struct v4l2_ctrl *ctrl); struct v4l2_ctrl *master; + ctrl_to_user = def_value ? def_to_user : cur_to_user; + if (helpers[i].mref == NULL) continue; @@ -2841,8 +2859,9 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs v4l2_ctrl_lock(master); /* g_volatile_ctrl will update the new control values */ - if ((master->flags & V4L2_CTRL_FLAG_VOLATILE) || - (master->has_volatiles && !is_cur_manual(master))) { + if (!def_value && + ((master->flags & V4L2_CTRL_FLAG_VOLATILE) || + (master->has_volatiles && !is_cur_manual(master)))) { for (j = 0; j < master->ncontrols; j++) cur_to_new(master->cluster[j]); ret = call_op(master, g_volatile_ctrl); @@ -3064,13 +3083,18 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, int ret; cs->error_idx = cs->count; - cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class); + + /* Default value cannot be changed */ + if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) + return -EINVAL; + + cs->which = V4L2_CTRL_ID2WHICH(cs->which); if (hdl == NULL) return -EINVAL; if (cs->count == 0) - return class_check(hdl, cs->ctrl_class); + return class_check(hdl, cs->which); if (cs->count > ARRAY_SIZE(helper)) { helpers = kmalloc_array(cs->count, sizeof(helper[0]), @@ -3300,7 +3324,8 @@ EXPORT_SYMBOL(v4l2_ctrl_notify); int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, s64 min, s64 max, u64 step, s64 def) { - bool changed; + bool value_changed; + bool range_changed = false; int ret; lockdep_assert_held(ctrl->handler->lock); @@ -3324,10 +3349,14 @@ int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, default: return -EINVAL; } - ctrl->minimum = min; - ctrl->maximum = max; - ctrl->step = step; - ctrl->default_value = def; + if ((ctrl->minimum != min) || (ctrl->maximum != max) || + (ctrl->step != step) || ctrl->default_value != def) { + range_changed = true; + ctrl->minimum = min; + ctrl->maximum = max; + ctrl->step = step; + ctrl->default_value = def; + } cur_to_new(ctrl); if (validate_new(ctrl, ctrl->p_new)) { if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) @@ -3337,12 +3366,12 @@ int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, } if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) - changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64; + value_changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64; else - changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32; - if (changed) + value_changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32; + if (value_changed) ret = set_ctrl(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); - else + else if (range_changed) send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); return ret; } diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 5b0a30b9252b..7129e438f29e 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -118,11 +118,20 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) { struct i2c_client *client = v4l2_get_subdevdata(sd); - /* We need to unregister the i2c client explicitly. - We cannot rely on i2c_del_adapter to always - unregister clients for us, since if the i2c bus - is a platform bus, then it is never deleted. */ - if (client) + /* + * We need to unregister the i2c client + * explicitly. We cannot rely on + * i2c_del_adapter to always unregister + * clients for us, since if the i2c bus is a + * platform bus, then it is never deleted. + * + * Device tree or ACPI based devices must not + * be unregistered as they have not been + * registered by us, and would not be + * re-created by just probing the V4L2 driver. + */ + if (client && + !client->dev.of_node && !client->dev.fwnode) i2c_unregister_device(client); continue; } @@ -131,7 +140,7 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) if (sd->flags & V4L2_SUBDEV_FL_IS_SPI) { struct spi_device *spi = v4l2_get_subdevdata(sd); - if (spi) + if (spi && !spi->dev.of_node && !spi->dev.fwnode) spi_unregister_device(spi); continue; } diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index 6a83d6191684..ec258b73001a 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -209,8 +209,13 @@ bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t, if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap, fnc, fnc_handle) && v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i, - pclock_delta)) { + pclock_delta, false)) { + u32 flags = t->bt.flags & V4L2_DV_FL_REDUCED_FPS; + *t = v4l2_dv_timings_presets[i]; + if (can_reduce_fps(&t->bt)) + t->bt.flags |= flags; + return true; } } @@ -223,12 +228,14 @@ EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cap); * @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. */ bool v4l2_match_dv_timings(const struct v4l2_dv_timings *t1, const struct v4l2_dv_timings *t2, - unsigned pclock_delta) + unsigned pclock_delta, bool match_reduced_fps) { if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120) return false; @@ -239,9 +246,14 @@ bool v4l2_match_dv_timings(const struct v4l2_dv_timings *t1, t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta && t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta && t1->bt.hfrontporch == t2->bt.hfrontporch && + t1->bt.hsync == t2->bt.hsync && + t1->bt.hbackporch == t2->bt.hbackporch && t1->bt.vfrontporch == t2->bt.vfrontporch && t1->bt.vsync == t2->bt.vsync && t1->bt.vbackporch == t2->bt.vbackporch && + (!match_reduced_fps || + (t1->bt.flags & V4L2_DV_FL_REDUCED_FPS) == + (t2->bt.flags & V4L2_DV_FL_REDUCED_FPS)) && (!t1->bt.interlaced || (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch && t1->bt.il_vsync == t2->bt.il_vsync && diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 7486af2c8ae4..8a018c6dd16a 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -565,8 +565,8 @@ static void v4l_print_ext_controls(const void *arg, bool write_only) const struct v4l2_ext_controls *p = arg; int i; - pr_cont("class=0x%x, count=%d, error_idx=%d", - p->ctrl_class, p->count, p->error_idx); + pr_cont("which=0x%x, count=%d, error_idx=%d", + p->which, p->count, p->error_idx); for (i = 0; i < p->count; i++) { if (!p->controls[i].size) pr_cont(", id/val=0x%x/0x%x", @@ -902,13 +902,13 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL is it allowed for backwards compatibility. */ - if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE) + if (!allow_priv && c->which == V4L2_CID_PRIVATE_BASE) return 0; - if (c->ctrl_class == 0) + if (!c->which) return 1; /* Check that all controls are from the same control class. */ for (i = 0; i < c->count; i++) { - if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) { + if (V4L2_CTRL_ID2WHICH(c->controls[i].id) != c->which) { c->error_idx = i; return 0; } @@ -1969,7 +1969,7 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, if (ops->vidioc_g_ext_ctrls == NULL) return -ENOTTY; - ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); + ctrls.which = V4L2_CTRL_ID2WHICH(p->id); ctrls.count = 1; ctrls.controls = &ctrl; ctrl.id = p->id; @@ -2003,7 +2003,7 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, if (ops->vidioc_s_ext_ctrls == NULL) return -ENOTTY; - ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); + ctrls.which = V4L2_CTRL_ID2WHICH(p->id); ctrls.count = 1; ctrls.controls = &ctrl; ctrl.id = p->id; diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 33bdd81065e8..c5d49d7a0d76 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -28,11 +28,161 @@ #include <trace/events/vb2.h> -#include "videobuf2-internal.h" +static int debug; +module_param(debug, int, 0644); -int vb2_debug; -EXPORT_SYMBOL_GPL(vb2_debug); -module_param_named(debug, vb2_debug, int, 0644); +#define dprintk(level, fmt, arg...) \ + do { \ + if (debug >= level) \ + pr_info("vb2-core: %s: " fmt, __func__, ## arg); \ + } while (0) + +#ifdef CONFIG_VIDEO_ADV_DEBUG + +/* + * If advanced debugging is on, then count how often each op is called + * successfully, which can either be per-buffer or per-queue. + * + * This makes it easy to check that the 'init' and 'cleanup' + * (and variations thereof) stay balanced. + */ + +#define log_memop(vb, op) \ + dprintk(2, "call_memop(%p, %d, %s)%s\n", \ + (vb)->vb2_queue, (vb)->index, #op, \ + (vb)->vb2_queue->mem_ops->op ? "" : " (nop)") + +#define call_memop(vb, op, args...) \ +({ \ + struct vb2_queue *_q = (vb)->vb2_queue; \ + int err; \ + \ + log_memop(vb, op); \ + err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0; \ + if (!err) \ + (vb)->cnt_mem_ ## op++; \ + err; \ +}) + +#define call_ptr_memop(vb, op, args...) \ +({ \ + struct vb2_queue *_q = (vb)->vb2_queue; \ + void *ptr; \ + \ + log_memop(vb, op); \ + ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL; \ + if (!IS_ERR_OR_NULL(ptr)) \ + (vb)->cnt_mem_ ## op++; \ + ptr; \ +}) + +#define call_void_memop(vb, op, args...) \ +({ \ + struct vb2_queue *_q = (vb)->vb2_queue; \ + \ + log_memop(vb, op); \ + if (_q->mem_ops->op) \ + _q->mem_ops->op(args); \ + (vb)->cnt_mem_ ## op++; \ +}) + +#define log_qop(q, op) \ + dprintk(2, "call_qop(%p, %s)%s\n", q, #op, \ + (q)->ops->op ? "" : " (nop)") + +#define call_qop(q, op, args...) \ +({ \ + int err; \ + \ + log_qop(q, op); \ + err = (q)->ops->op ? (q)->ops->op(args) : 0; \ + if (!err) \ + (q)->cnt_ ## op++; \ + err; \ +}) + +#define call_void_qop(q, op, args...) \ +({ \ + log_qop(q, op); \ + if ((q)->ops->op) \ + (q)->ops->op(args); \ + (q)->cnt_ ## op++; \ +}) + +#define log_vb_qop(vb, op, args...) \ + dprintk(2, "call_vb_qop(%p, %d, %s)%s\n", \ + (vb)->vb2_queue, (vb)->index, #op, \ + (vb)->vb2_queue->ops->op ? "" : " (nop)") + +#define call_vb_qop(vb, op, args...) \ +({ \ + int err; \ + \ + log_vb_qop(vb, op); \ + err = (vb)->vb2_queue->ops->op ? \ + (vb)->vb2_queue->ops->op(args) : 0; \ + if (!err) \ + (vb)->cnt_ ## op++; \ + err; \ +}) + +#define call_void_vb_qop(vb, op, args...) \ +({ \ + log_vb_qop(vb, op); \ + if ((vb)->vb2_queue->ops->op) \ + (vb)->vb2_queue->ops->op(args); \ + (vb)->cnt_ ## op++; \ +}) + +#else + +#define call_memop(vb, op, args...) \ + ((vb)->vb2_queue->mem_ops->op ? \ + (vb)->vb2_queue->mem_ops->op(args) : 0) + +#define call_ptr_memop(vb, op, args...) \ + ((vb)->vb2_queue->mem_ops->op ? \ + (vb)->vb2_queue->mem_ops->op(args) : NULL) + +#define call_void_memop(vb, op, args...) \ + do { \ + if ((vb)->vb2_queue->mem_ops->op) \ + (vb)->vb2_queue->mem_ops->op(args); \ + } while (0) + +#define call_qop(q, op, args...) \ + ((q)->ops->op ? (q)->ops->op(args) : 0) + +#define call_void_qop(q, op, args...) \ + do { \ + if ((q)->ops->op) \ + (q)->ops->op(args); \ + } while (0) + +#define call_vb_qop(vb, op, args...) \ + ((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0) + +#define call_void_vb_qop(vb, op, args...) \ + do { \ + if ((vb)->vb2_queue->ops->op) \ + (vb)->vb2_queue->ops->op(args); \ + } while (0) + +#endif + +#define call_bufop(q, op, args...) \ +({ \ + int ret = 0; \ + if (q && q->buf_ops && q->buf_ops->op) \ + ret = q->buf_ops->op(args); \ + ret; \ +}) + +#define call_void_bufop(q, op, args...) \ +({ \ + if (q && q->buf_ops && q->buf_ops->op) \ + q->buf_ops->op(args); \ +}) static void __vb2_queue_cancel(struct vb2_queue *q); static void __enqueue_in_driver(struct vb2_buffer *vb); @@ -53,7 +203,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) * NOTE: mmapped areas should be page aligned */ for (plane = 0; plane < vb->num_planes; ++plane) { - unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]); + unsigned long size = PAGE_ALIGN(vb->planes[plane].length); mem_priv = call_ptr_memop(vb, alloc, q->alloc_ctx[plane], size, dma_dir, q->gfp_flags); @@ -62,7 +212,6 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) /* Associate allocator private data with this plane */ vb->planes[plane].mem_priv = mem_priv; - vb->planes[plane].length = q->plane_sizes[plane]; } return 0; @@ -137,57 +286,30 @@ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb) } /** - * __setup_lengths() - setup initial lengths for every plane in - * every buffer on the queue - */ -static void __setup_lengths(struct vb2_queue *q, unsigned int n) -{ - unsigned int buffer, plane; - struct vb2_buffer *vb; - - for (buffer = q->num_buffers; buffer < q->num_buffers + n; ++buffer) { - vb = q->bufs[buffer]; - if (!vb) - continue; - - for (plane = 0; plane < vb->num_planes; ++plane) - vb->planes[plane].length = q->plane_sizes[plane]; - } -} - -/** * __setup_offsets() - setup unique offsets ("cookies") for every plane in - * every buffer on the queue + * the buffer. */ -static void __setup_offsets(struct vb2_queue *q, unsigned int n) +static void __setup_offsets(struct vb2_buffer *vb) { - unsigned int buffer, plane; - struct vb2_buffer *vb; - unsigned long off; + struct vb2_queue *q = vb->vb2_queue; + unsigned int plane; + unsigned long off = 0; + + if (vb->index) { + struct vb2_buffer *prev = q->bufs[vb->index - 1]; + struct vb2_plane *p = &prev->planes[prev->num_planes - 1]; - if (q->num_buffers) { - struct vb2_plane *p; - vb = q->bufs[q->num_buffers - 1]; - p = &vb->planes[vb->num_planes - 1]; off = PAGE_ALIGN(p->m.offset + p->length); - } else { - off = 0; } - for (buffer = q->num_buffers; buffer < q->num_buffers + n; ++buffer) { - vb = q->bufs[buffer]; - if (!vb) - continue; - - for (plane = 0; plane < vb->num_planes; ++plane) { - vb->planes[plane].m.offset = off; + for (plane = 0; plane < vb->num_planes; ++plane) { + vb->planes[plane].m.offset = off; - dprintk(3, "buffer %d, plane %d offset 0x%08lx\n", - buffer, plane, off); + dprintk(3, "buffer %d, plane %d offset 0x%08lx\n", + vb->index, plane, off); - off += vb->planes[plane].length; - off = PAGE_ALIGN(off); - } + off += vb->planes[plane].length; + off = PAGE_ALIGN(off); } } @@ -199,9 +321,10 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n) * Returns the number of buffers successfully allocated. */ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory, - unsigned int num_buffers, unsigned int num_planes) + unsigned int num_buffers, unsigned int num_planes, + const unsigned plane_sizes[VB2_MAX_PLANES]) { - unsigned int buffer; + unsigned int buffer, plane; struct vb2_buffer *vb; int ret; @@ -219,6 +342,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory, vb->index = q->num_buffers + buffer; vb->type = q->type; vb->memory = memory; + for (plane = 0; plane < num_planes; ++plane) { + vb->planes[plane].length = plane_sizes[plane]; + vb->planes[plane].min_length = plane_sizes[plane]; + } + q->bufs[vb->index] = vb; /* Allocate video buffer memory for the MMAP type */ if (memory == VB2_MEMORY_MMAP) { @@ -226,9 +354,11 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory, if (ret) { dprintk(1, "failed allocating memory for " "buffer %d\n", buffer); + q->bufs[vb->index] = NULL; kfree(vb); break; } + __setup_offsets(vb); /* * Call the driver-provided buffer initialization * callback, if given. An error in initialization @@ -239,18 +369,13 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory, dprintk(1, "buffer %d %p initialization" " failed\n", buffer, vb); __vb2_buf_mem_free(vb); + q->bufs[vb->index] = NULL; kfree(vb); break; } } - - q->bufs[q->num_buffers + buffer] = vb; } - __setup_lengths(q, buffer); - if (memory == VB2_MEMORY_MMAP) - __setup_offsets(q, buffer); - dprintk(1, "allocated %d buffers, %d plane(s) each\n", buffer, num_planes); @@ -330,7 +455,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) bool unbalanced = q->cnt_start_streaming != q->cnt_stop_streaming || q->cnt_wait_prepare != q->cnt_wait_finish; - if (unbalanced || vb2_debug) { + if (unbalanced || debug) { pr_info("vb2: counters for queue %p:%s\n", q, unbalanced ? " UNBALANCED!" : ""); pr_info("vb2: setup: %u start_streaming: %u stop_streaming: %u\n", @@ -356,7 +481,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) vb->cnt_buf_prepare != vb->cnt_buf_finish || vb->cnt_buf_init != vb->cnt_buf_cleanup; - if (unbalanced || vb2_debug) { + if (unbalanced || debug) { pr_info("vb2: counters for queue %p, buffer %d:%s\n", q, buffer, unbalanced ? " UNBALANCED!" : ""); pr_info("vb2: buf_init: %u buf_cleanup: %u buf_prepare: %u buf_finish: %u\n", @@ -442,13 +567,10 @@ static bool __buffers_in_use(struct vb2_queue *q) * Should be called from vidioc_querybuf ioctl handler in driver. * The passed buffer should have been verified. * This function fills the relevant information for the userspace. - * - * The return values from this function are intended to be directly returned - * from vidioc_querybuf handler in driver. */ -int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb) +void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb) { - return call_bufop(q, fill_user_buffer, q->bufs[index], pb); + call_void_bufop(q, fill_user_buffer, q->bufs[index], pb); } EXPORT_SYMBOL_GPL(vb2_core_querybuf); @@ -570,6 +692,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, unsigned int *count) { unsigned int num_buffers, allocated_buffers, num_planes = 0; + unsigned plane_sizes[VB2_MAX_PLANES] = { }; int ret; if (q->streaming) { @@ -613,7 +736,6 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, */ num_buffers = min_t(unsigned int, *count, VB2_MAX_FRAME); num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed); - memset(q->plane_sizes, 0, sizeof(q->plane_sizes)); memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); q->memory = memory; @@ -621,14 +743,14 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, * Ask the driver how many buffers and planes per buffer it requires. * Driver also sets the size and allocator context for each plane. */ - ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes, - q->plane_sizes, q->alloc_ctx); + ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes, + plane_sizes, q->alloc_ctx); if (ret) return ret; /* Finally, allocate buffers and video memory */ allocated_buffers = - __vb2_queue_alloc(q, memory, num_buffers, num_planes); + __vb2_queue_alloc(q, memory, num_buffers, num_planes, plane_sizes); if (allocated_buffers == 0) { dprintk(1, "memory allocation failed\n"); return -ENOMEM; @@ -646,9 +768,16 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, */ if (!ret && allocated_buffers < num_buffers) { num_buffers = allocated_buffers; + /* + * num_planes is set by the previous queue_setup(), but since it + * signals to queue_setup() whether it is called from create_bufs() + * vs reqbufs() we zero it here to signal that queue_setup() is + * called for the reqbufs() case. + */ + num_planes = 0; - ret = call_qop(q, queue_setup, q, NULL, &num_buffers, - &num_planes, q->plane_sizes, q->alloc_ctx); + ret = call_qop(q, queue_setup, q, &num_buffers, + &num_planes, plane_sizes, q->alloc_ctx); if (!ret && allocated_buffers < num_buffers) ret = -ENOMEM; @@ -701,9 +830,11 @@ EXPORT_SYMBOL_GPL(vb2_core_reqbufs); * from vidioc_create_bufs handler in driver. */ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, - unsigned int *count, const void *parg) + unsigned int *count, unsigned requested_planes, + const unsigned requested_sizes[]) { unsigned int num_planes = 0, num_buffers, allocated_buffers; + unsigned plane_sizes[VB2_MAX_PLANES] = { }; int ret; if (q->num_buffers == VB2_MAX_FRAME) { @@ -712,7 +843,6 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, } if (!q->num_buffers) { - memset(q->plane_sizes, 0, sizeof(q->plane_sizes)); memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); q->memory = memory; q->waiting_for_buffers = !q->is_output; @@ -720,18 +850,23 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers); + if (requested_planes && requested_sizes) { + num_planes = requested_planes; + memcpy(plane_sizes, requested_sizes, sizeof(plane_sizes)); + } + /* * Ask the driver, whether the requested number of buffers, planes per * buffer and their sizes are acceptable */ - ret = call_qop(q, queue_setup, q, parg, &num_buffers, - &num_planes, q->plane_sizes, q->alloc_ctx); + ret = call_qop(q, queue_setup, q, &num_buffers, + &num_planes, plane_sizes, q->alloc_ctx); if (ret) return ret; /* Finally, allocate buffers and video memory */ allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers, - num_planes); + num_planes, plane_sizes); if (allocated_buffers == 0) { dprintk(1, "memory allocation failed\n"); return -ENOMEM; @@ -747,8 +882,8 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, * q->num_buffers contains the total number of buffers, that the * queue driver has set up */ - ret = call_qop(q, queue_setup, q, parg, &num_buffers, - &num_planes, q->plane_sizes, q->alloc_ctx); + ret = call_qop(q, queue_setup, q, &num_buffers, + &num_planes, plane_sizes, q->alloc_ctx); if (!ret && allocated_buffers < num_buffers) ret = -ENOMEM; @@ -964,11 +1099,12 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) "reacquiring memory\n", plane); /* Check if the provided plane buffer is large enough */ - if (planes[plane].length < q->plane_sizes[plane]) { + if (planes[plane].length < vb->planes[plane].min_length) { dprintk(1, "provided buffer size %u is less than " "setup size %u for plane %d\n", planes[plane].length, - q->plane_sizes[plane], plane); + vb->planes[plane].min_length, + plane); ret = -EINVAL; goto err; } @@ -1081,7 +1217,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) if (planes[plane].length == 0) planes[plane].length = dbuf->size; - if (planes[plane].length < q->plane_sizes[plane]) { + if (planes[plane].length < vb->planes[plane].min_length) { dprintk(1, "invalid dmabuf length for plane %d\n", plane); ret = -EINVAL; @@ -1263,9 +1399,7 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb) return ret; /* Fill buffer information for the userspace */ - ret = call_bufop(q, fill_user_buffer, vb, pb); - if (ret) - return ret; + call_void_bufop(q, fill_user_buffer, vb, pb); dprintk(1, "prepare of buffer %d succeeded\n", vb->index); @@ -1386,7 +1520,7 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) q->waiting_for_buffers = false; vb->state = VB2_BUF_STATE_QUEUED; - call_bufop(q, set_timestamp, vb, pb); + call_void_bufop(q, copy_timestamp, vb, pb); trace_vb2_qbuf(q, vb); @@ -1398,9 +1532,7 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) __enqueue_in_driver(vb); /* Fill buffer information for the userspace */ - ret = call_bufop(q, fill_user_buffer, vb, pb); - if (ret) - return ret; + call_void_bufop(q, fill_user_buffer, vb, pb); /* * If streamon has been called, and we haven't yet called @@ -1623,9 +1755,7 @@ int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking) call_void_vb_qop(vb, buf_finish, vb); /* Fill buffer information for the userspace */ - ret = call_bufop(q, fill_user_buffer, vb, pb); - if (ret) - return ret; + call_void_bufop(q, fill_user_buffer, vb, pb); /* Remove from videobuf queue */ list_del(&vb->queued_entry); @@ -2073,6 +2203,8 @@ int vb2_core_queue_init(struct vb2_queue *q) } EXPORT_SYMBOL_GPL(vb2_core_queue_init); +static int __vb2_init_fileio(struct vb2_queue *q, int read); +static int __vb2_cleanup_fileio(struct vb2_queue *q); /** * vb2_core_queue_release() - stop streaming, release the queue and free memory * @q: videobuf2 queue @@ -2083,6 +2215,7 @@ EXPORT_SYMBOL_GPL(vb2_core_queue_init); */ void vb2_core_queue_release(struct vb2_queue *q) { + __vb2_cleanup_fileio(q); __vb2_queue_cancel(q); mutex_lock(&q->mmap_lock); __vb2_queue_free(q, q->num_buffers); @@ -2090,6 +2223,619 @@ void vb2_core_queue_release(struct vb2_queue *q) } EXPORT_SYMBOL_GPL(vb2_core_queue_release); -MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2"); +/** + * vb2_core_poll() - implements poll userspace operation + * @q: videobuf2 queue + * @file: file argument passed to the poll file operation handler + * @wait: wait argument passed to the poll file operation handler + * + * This function implements poll file operation handler for a driver. + * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will + * be informed that the file descriptor of a video device is available for + * reading. + * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor + * will be reported as available for writing. + * + * The return values from this function are intended to be directly returned + * from poll handler in driver. + */ +unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file, + poll_table *wait) +{ + unsigned long req_events = poll_requested_events(wait); + struct vb2_buffer *vb = NULL; + unsigned long flags; + + if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM))) + return 0; + if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM))) + return 0; + + /* + * Start file I/O emulator only if streaming API has not been used yet. + */ + if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) { + if (!q->is_output && (q->io_modes & VB2_READ) && + (req_events & (POLLIN | POLLRDNORM))) { + if (__vb2_init_fileio(q, 1)) + return POLLERR; + } + if (q->is_output && (q->io_modes & VB2_WRITE) && + (req_events & (POLLOUT | POLLWRNORM))) { + if (__vb2_init_fileio(q, 0)) + return POLLERR; + /* + * Write to OUTPUT queue can be done immediately. + */ + return POLLOUT | POLLWRNORM; + } + } + + /* + * There is nothing to wait for if the queue isn't streaming, or if the + * error flag is set. + */ + if (!vb2_is_streaming(q) || q->error) + return POLLERR; + + /* + * For output streams you can call write() as long as there are fewer + * buffers queued than there are buffers available. + */ + if (q->is_output && q->fileio && q->queued_count < q->num_buffers) + return POLLOUT | POLLWRNORM; + + if (list_empty(&q->done_list)) { + /* + * If the last buffer was dequeued from a capture queue, + * return immediately. DQBUF will return -EPIPE. + */ + if (q->last_buffer_dequeued) + return POLLIN | POLLRDNORM; + + poll_wait(file, &q->done_wq, wait); + } + + /* + * Take first buffer available for dequeuing. + */ + spin_lock_irqsave(&q->done_lock, flags); + if (!list_empty(&q->done_list)) + vb = list_first_entry(&q->done_list, struct vb2_buffer, + done_entry); + spin_unlock_irqrestore(&q->done_lock, flags); + + if (vb && (vb->state == VB2_BUF_STATE_DONE + || vb->state == VB2_BUF_STATE_ERROR)) { + return (q->is_output) ? + POLLOUT | POLLWRNORM : + POLLIN | POLLRDNORM; + } + return 0; +} +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 + * write) calls on top of streaming API. This structure is used for + * tracking context related to the buffers. + */ +struct vb2_fileio_buf { + void *vaddr; + unsigned int size; + unsigned int pos; + 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 + * written to. If equal to q->num_buffers then a new buffer + * must be dequeued. + * @initial_index: in the read() case all buffers are queued up immediately + * in __vb2_init_fileio() and __vb2_perform_fileio() just cycles + * buffers. However, in the write() case no buffers are initially + * queued, instead whenever a buffer is full it is queued up by + * __vb2_perform_fileio(). Only once all available buffers have + * been queued up will __vb2_perform_fileio() start to dequeue + * buffers. This means that initially __vb2_perform_fileio() + * needs to know what buffer index to use when it is queuing up + * the buffers for the first time. That initial index is stored + * in this field. Once it is equal to q->num_buffers all + * available buffers have been queued and __vb2_perform_fileio() + * should start the normal dequeue/queue cycle. + * + * vb2 provides a compatibility layer and emulator of file io (read and + * write) calls on top of streaming API. For proper operation it required + * this structure to save the driver state between each call of the read + * or write function. + */ +struct vb2_fileio_data { + unsigned int count; + unsigned int type; + unsigned int memory; + struct vb2_buffer *b; + struct vb2_fileio_buf bufs[VB2_MAX_FRAME]; + unsigned int cur_index; + unsigned int initial_index; + unsigned int q_count; + unsigned int dq_count; + unsigned read_once:1; + unsigned write_immediately:1; +}; + +/** + * __vb2_init_fileio() - initialize file io emulator + * @q: videobuf2 queue + * @read: mode selector (1 means read, 0 means write) + */ +static int __vb2_init_fileio(struct vb2_queue *q, int read) +{ + struct vb2_fileio_data *fileio; + int i, ret; + unsigned int count = 0; + + /* + * Sanity check + */ + if (WARN_ON((read && !(q->io_modes & VB2_READ)) || + (!read && !(q->io_modes & VB2_WRITE)))) + return -EINVAL; + + /* + * Check if device supports mapping buffers to kernel virtual space. + */ + if (!q->mem_ops->vaddr) + return -EBUSY; + + /* + * Check if streaming api has not been already activated. + */ + if (q->streaming || q->num_buffers > 0) + return -EBUSY; + + /* + * Start with count 1, driver can increase it in queue_setup() + */ + count = 1; + + dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n", + (read) ? "read" : "write", count, q->fileio_read_once, + q->fileio_write_immediately); + + fileio = kzalloc(sizeof(*fileio), GFP_KERNEL); + if (fileio == NULL) + return -ENOMEM; + + fileio->b = kzalloc(q->buf_struct_size, GFP_KERNEL); + if (fileio->b == NULL) { + kfree(fileio); + return -ENOMEM; + } + + fileio->read_once = q->fileio_read_once; + fileio->write_immediately = q->fileio_write_immediately; + + /* + * Request buffers and use MMAP type to force driver + * to allocate buffers by itself. + */ + fileio->count = count; + fileio->memory = VB2_MEMORY_MMAP; + fileio->type = q->type; + q->fileio = fileio; + ret = vb2_core_reqbufs(q, fileio->memory, &fileio->count); + if (ret) + goto err_kfree; + + /* + * Check if plane_count is correct + * (multiplane buffers are not supported). + */ + if (q->bufs[0]->num_planes != 1) { + ret = -EBUSY; + goto err_reqbufs; + } + + /* + * Get kernel address of each buffer. + */ + for (i = 0; i < q->num_buffers; i++) { + fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0); + if (fileio->bufs[i].vaddr == NULL) { + ret = -EINVAL; + goto err_reqbufs; + } + fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0); + } + + /* + * Read mode requires pre queuing of all buffers. + */ + if (read) { + /* + * Queue all buffers. + */ + for (i = 0; i < q->num_buffers; i++) { + struct vb2_buffer *b = fileio->b; + + memset(b, 0, q->buf_struct_size); + b->type = q->type; + b->memory = q->memory; + b->index = i; + ret = vb2_core_qbuf(q, i, b); + if (ret) + goto err_reqbufs; + fileio->bufs[i].queued = 1; + } + /* + * All buffers have been queued, so mark that by setting + * initial_index to q->num_buffers + */ + fileio->initial_index = q->num_buffers; + fileio->cur_index = q->num_buffers; + } + + /* + * Start streaming. + */ + ret = vb2_core_streamon(q, q->type); + if (ret) + goto err_reqbufs; + + return ret; + +err_reqbufs: + fileio->count = 0; + vb2_core_reqbufs(q, fileio->memory, &fileio->count); + +err_kfree: + q->fileio = NULL; + kfree(fileio); + return ret; +} + +/** + * __vb2_cleanup_fileio() - free resourced used by file io emulator + * @q: videobuf2 queue + */ +static int __vb2_cleanup_fileio(struct vb2_queue *q) +{ + struct vb2_fileio_data *fileio = q->fileio; + + if (fileio) { + vb2_core_streamoff(q, q->type); + q->fileio = NULL; + fileio->count = 0; + vb2_core_reqbufs(q, fileio->memory, &fileio->count); + kfree(fileio->b); + kfree(fileio); + dprintk(3, "file io emulator closed\n"); + } + return 0; +} + +/** + * __vb2_perform_fileio() - perform a single file io (read or write) operation + * @q: videobuf2 queue + * @data: pointed to target userspace buffer + * @count: number of bytes to read or write + * @ppos: file handle position tracking pointer + * @nonblock: mode selector (1 means blocking calls, 0 means nonblocking) + * @read: access mode selector (1 means read, 0 means write) + */ +static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count, + loff_t *ppos, int nonblock, int read) +{ + struct vb2_fileio_data *fileio; + struct vb2_fileio_buf *buf; + bool is_multiplanar = q->is_multiplanar; + /* + * When using write() to write data to an output video node the vb2 core + * should copy timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody + * else is able to provide this information with the write() operation. + */ + bool copy_timestamp = !read && q->copy_timestamp; + int ret, index; + + dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n", + read ? "read" : "write", (long)*ppos, count, + nonblock ? "non" : ""); + + if (!data) + return -EINVAL; + + /* + * Initialize emulator on first call. + */ + if (!vb2_fileio_is_active(q)) { + ret = __vb2_init_fileio(q, read); + dprintk(3, "vb2_init_fileio result: %d\n", ret); + if (ret) + return ret; + } + fileio = q->fileio; + + /* + * Check if we need to dequeue the buffer. + */ + index = fileio->cur_index; + if (index >= q->num_buffers) { + struct vb2_buffer *b = fileio->b; + + /* + * Call vb2_dqbuf to get buffer back. + */ + memset(b, 0, q->buf_struct_size); + b->type = q->type; + b->memory = q->memory; + ret = vb2_core_dqbuf(q, b, nonblock); + dprintk(5, "vb2_dqbuf result: %d\n", ret); + if (ret) + return ret; + fileio->dq_count += 1; + + fileio->cur_index = index = b->index; + buf = &fileio->bufs[index]; + + /* + * Get number of bytes filled by the driver + */ + buf->pos = 0; + buf->queued = 0; + buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0) + : vb2_plane_size(q->bufs[index], 0); + /* Compensate for data_offset on read in the multiplanar case. */ + if (is_multiplanar && read && + b->planes[0].data_offset < buf->size) { + buf->pos = b->planes[0].data_offset; + buf->size -= buf->pos; + } + } else { + buf = &fileio->bufs[index]; + } + + /* + * Limit count on last few bytes of the buffer. + */ + if (buf->pos + count > buf->size) { + count = buf->size - buf->pos; + dprintk(5, "reducing read count: %zd\n", count); + } + + /* + * Transfer data to userspace. + */ + dprintk(3, "copying %zd bytes - buffer %d, offset %u\n", + count, index, buf->pos); + if (read) + ret = copy_to_user(data, buf->vaddr + buf->pos, count); + else + ret = copy_from_user(buf->vaddr + buf->pos, data, count); + if (ret) { + dprintk(3, "error copying data\n"); + return -EFAULT; + } + + /* + * Update counters. + */ + buf->pos += count; + *ppos += count; + + /* + * Queue next buffer if required. + */ + if (buf->pos == buf->size || (!read && fileio->write_immediately)) { + struct vb2_buffer *b = fileio->b; + + /* + * Check if this is the last buffer to read. + */ + if (read && fileio->read_once && fileio->dq_count == 1) { + dprintk(3, "read limit reached\n"); + return __vb2_cleanup_fileio(q); + } + + /* + * Call vb2_qbuf and give buffer to the driver. + */ + memset(b, 0, q->buf_struct_size); + b->type = q->type; + b->memory = q->memory; + b->index = index; + b->planes[0].bytesused = buf->pos; + + if (copy_timestamp) + b->timestamp = ktime_get_ns(); + ret = vb2_core_qbuf(q, index, b); + dprintk(5, "vb2_dbuf result: %d\n", ret); + if (ret) + return ret; + + /* + * Buffer has been queued, update the status + */ + buf->pos = 0; + buf->queued = 1; + buf->size = vb2_plane_size(q->bufs[index], 0); + fileio->q_count += 1; + /* + * If we are queuing up buffers for the first time, then + * increase initial_index by one. + */ + if (fileio->initial_index < q->num_buffers) + fileio->initial_index++; + /* + * The next buffer to use is either a buffer that's going to be + * queued for the first time (initial_index < q->num_buffers) + * or it is equal to q->num_buffers, meaning that the next + * time we need to dequeue a buffer since we've now queued up + * all the 'first time' buffers. + */ + fileio->cur_index = fileio->initial_index; + } + + /* + * Return proper number of bytes processed. + */ + if (ret == 0) + ret = count; + return ret; +} + +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count, + loff_t *ppos, int nonblocking) +{ + return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1); +} +EXPORT_SYMBOL_GPL(vb2_read); + +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count, + loff_t *ppos, int nonblocking) +{ + return __vb2_perform_fileio(q, (char __user *) data, count, + ppos, nonblocking, 0); +} +EXPORT_SYMBOL_GPL(vb2_write); + +struct vb2_threadio_data { + struct task_struct *thread; + vb2_thread_fnc fnc; + void *priv; + bool stop; +}; + +static int vb2_thread(void *data) +{ + struct vb2_queue *q = data; + struct vb2_threadio_data *threadio = q->threadio; + struct vb2_fileio_data *fileio = q->fileio; + bool copy_timestamp = false; + int prequeue = 0; + int index = 0; + int ret = 0; + + if (q->is_output) { + prequeue = q->num_buffers; + copy_timestamp = q->copy_timestamp; + } + + set_freezable(); + + for (;;) { + struct vb2_buffer *vb; + struct vb2_buffer *b = fileio->b; + + /* + * Call vb2_dqbuf to get buffer back. + */ + memset(b, 0, q->buf_struct_size); + b->type = q->type; + b->memory = q->memory; + if (prequeue) { + b->index = index++; + prequeue--; + } else { + call_void_qop(q, wait_finish, q); + if (!threadio->stop) + ret = vb2_core_dqbuf(q, b, 0); + call_void_qop(q, wait_prepare, q); + dprintk(5, "file io: vb2_dqbuf result: %d\n", ret); + } + if (ret || threadio->stop) + break; + try_to_freeze(); + + vb = q->bufs[b->index]; + if (b->state == VB2_BUF_STATE_DONE) + if (threadio->fnc(vb, threadio->priv)) + break; + call_void_qop(q, wait_finish, q); + if (copy_timestamp) + b->timestamp = ktime_get_ns();; + if (!threadio->stop) + ret = vb2_core_qbuf(q, b->index, b); + call_void_qop(q, wait_prepare, q); + if (ret || threadio->stop) + break; + } + + /* Hmm, linux becomes *very* unhappy without this ... */ + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + return 0; +} + +/* + * This function should not be used for anything else but the videobuf2-dvb + * support. If you think you have another good use-case for this, then please + * contact the linux-media mailinglist first. + */ +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv, + const char *thread_name) +{ + struct vb2_threadio_data *threadio; + int ret = 0; + + if (q->threadio) + return -EBUSY; + if (vb2_is_busy(q)) + return -EBUSY; + if (WARN_ON(q->fileio)) + return -EBUSY; + + threadio = kzalloc(sizeof(*threadio), GFP_KERNEL); + if (threadio == NULL) + return -ENOMEM; + threadio->fnc = fnc; + threadio->priv = priv; + + ret = __vb2_init_fileio(q, !q->is_output); + dprintk(3, "file io: vb2_init_fileio result: %d\n", ret); + if (ret) + goto nomem; + q->threadio = threadio; + threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name); + if (IS_ERR(threadio->thread)) { + ret = PTR_ERR(threadio->thread); + threadio->thread = NULL; + goto nothread; + } + return 0; + +nothread: + __vb2_cleanup_fileio(q); +nomem: + kfree(threadio); + return ret; +} +EXPORT_SYMBOL_GPL(vb2_thread_start); + +int vb2_thread_stop(struct vb2_queue *q) +{ + struct vb2_threadio_data *threadio = q->threadio; + int err; + + if (threadio == NULL) + return 0; + threadio->stop = true; + /* Wake up all pending sleeps in the thread */ + vb2_queue_error(q); + err = kthread_stop(threadio->thread); + __vb2_cleanup_fileio(q); + threadio->thread = NULL; + kfree(threadio); + q->threadio = NULL; + return err; +} +EXPORT_SYMBOL_GPL(vb2_thread_stop); + +MODULE_DESCRIPTION("Media buffer core framework"); MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h deleted file mode 100644 index 79018c749282..000000000000 --- a/drivers/media/v4l2-core/videobuf2-internal.h +++ /dev/null @@ -1,161 +0,0 @@ -#ifndef _MEDIA_VIDEOBUF2_INTERNAL_H -#define _MEDIA_VIDEOBUF2_INTERNAL_H - -#include <linux/err.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <media/videobuf2-core.h> - -extern int vb2_debug; - -#define dprintk(level, fmt, arg...) \ - do { \ - if (vb2_debug >= level) \ - pr_info("vb2: %s: " fmt, __func__, ## arg); \ - } while (0) - -#ifdef CONFIG_VIDEO_ADV_DEBUG - -/* - * If advanced debugging is on, then count how often each op is called - * successfully, which can either be per-buffer or per-queue. - * - * This makes it easy to check that the 'init' and 'cleanup' - * (and variations thereof) stay balanced. - */ - -#define log_memop(vb, op) \ - dprintk(2, "call_memop(%p, %d, %s)%s\n", \ - (vb)->vb2_queue, (vb)->index, #op, \ - (vb)->vb2_queue->mem_ops->op ? "" : " (nop)") - -#define call_memop(vb, op, args...) \ -({ \ - struct vb2_queue *_q = (vb)->vb2_queue; \ - int err; \ - \ - log_memop(vb, op); \ - err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0; \ - if (!err) \ - (vb)->cnt_mem_ ## op++; \ - err; \ -}) - -#define call_ptr_memop(vb, op, args...) \ -({ \ - struct vb2_queue *_q = (vb)->vb2_queue; \ - void *ptr; \ - \ - log_memop(vb, op); \ - ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL; \ - if (!IS_ERR_OR_NULL(ptr)) \ - (vb)->cnt_mem_ ## op++; \ - ptr; \ -}) - -#define call_void_memop(vb, op, args...) \ -({ \ - struct vb2_queue *_q = (vb)->vb2_queue; \ - \ - log_memop(vb, op); \ - if (_q->mem_ops->op) \ - _q->mem_ops->op(args); \ - (vb)->cnt_mem_ ## op++; \ -}) - -#define log_qop(q, op) \ - dprintk(2, "call_qop(%p, %s)%s\n", q, #op, \ - (q)->ops->op ? "" : " (nop)") - -#define call_qop(q, op, args...) \ -({ \ - int err; \ - \ - log_qop(q, op); \ - err = (q)->ops->op ? (q)->ops->op(args) : 0; \ - if (!err) \ - (q)->cnt_ ## op++; \ - err; \ -}) - -#define call_void_qop(q, op, args...) \ -({ \ - log_qop(q, op); \ - if ((q)->ops->op) \ - (q)->ops->op(args); \ - (q)->cnt_ ## op++; \ -}) - -#define log_vb_qop(vb, op, args...) \ - dprintk(2, "call_vb_qop(%p, %d, %s)%s\n", \ - (vb)->vb2_queue, (vb)->index, #op, \ - (vb)->vb2_queue->ops->op ? "" : " (nop)") - -#define call_vb_qop(vb, op, args...) \ -({ \ - int err; \ - \ - log_vb_qop(vb, op); \ - err = (vb)->vb2_queue->ops->op ? \ - (vb)->vb2_queue->ops->op(args) : 0; \ - if (!err) \ - (vb)->cnt_ ## op++; \ - err; \ -}) - -#define call_void_vb_qop(vb, op, args...) \ -({ \ - log_vb_qop(vb, op); \ - if ((vb)->vb2_queue->ops->op) \ - (vb)->vb2_queue->ops->op(args); \ - (vb)->cnt_ ## op++; \ -}) - -#else - -#define call_memop(vb, op, args...) \ - ((vb)->vb2_queue->mem_ops->op ? \ - (vb)->vb2_queue->mem_ops->op(args) : 0) - -#define call_ptr_memop(vb, op, args...) \ - ((vb)->vb2_queue->mem_ops->op ? \ - (vb)->vb2_queue->mem_ops->op(args) : NULL) - -#define call_void_memop(vb, op, args...) \ - do { \ - if ((vb)->vb2_queue->mem_ops->op) \ - (vb)->vb2_queue->mem_ops->op(args); \ - } while (0) - -#define call_qop(q, op, args...) \ - ((q)->ops->op ? (q)->ops->op(args) : 0) - -#define call_void_qop(q, op, args...) \ - do { \ - if ((q)->ops->op) \ - (q)->ops->op(args); \ - } while (0) - -#define call_vb_qop(vb, op, args...) \ - ((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0) - -#define call_void_vb_qop(vb, op, args...) \ - do { \ - if ((vb)->vb2_queue->ops->op) \ - (vb)->vb2_queue->ops->op(args); \ - } while (0) - -#endif - -#define call_bufop(q, op, args...) \ -({ \ - int ret = 0; \ - if (q && q->buf_ops && q->buf_ops->op) \ - ret = q->buf_ops->op(args); \ - ret; \ -}) - -bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb); -int vb2_verify_memory_type(struct vb2_queue *q, - enum vb2_memory memory, unsigned int type); -#endif /* _MEDIA_VIDEOBUF2_INTERNAL_H */ diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index 27b4b9e7c0c2..c9a28605511a 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -31,7 +31,14 @@ #include <media/videobuf2-v4l2.h> -#include "videobuf2-internal.h" +static int debug; +module_param(debug, int, 0644); + +#define dprintk(level, fmt, arg...) \ + do { \ + if (debug >= level) \ + pr_info("vb2-v4l2: %s: " fmt, __func__, ## arg); \ + } while (0) /* Flags that are set by the vb2 core */ #define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \ @@ -52,7 +59,7 @@ static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer return 0; /* Is memory for copying plane information present? */ - if (NULL == b->m.planes) { + if (b->m.planes == NULL) { dprintk(1, "multi-planar buffer passed but " "planes array not provided\n"); return -EINVAL; @@ -107,7 +114,7 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) return 0; } -static int __set_timestamp(struct vb2_buffer *vb, const void *pb) +static void __copy_timestamp(struct vb2_buffer *vb, const void *pb) { const struct v4l2_buffer *b = pb; struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -118,14 +125,12 @@ static int __set_timestamp(struct vb2_buffer *vb, const void *pb) * For output buffers copy the timestamp if needed, * and the timecode field and flag if needed. */ - if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == - V4L2_BUF_FLAG_TIMESTAMP_COPY) - vbuf->timestamp = b->timestamp; + if (q->copy_timestamp) + vb->timestamp = timeval_to_ns(&b->timestamp); vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE; if (b->flags & V4L2_BUF_FLAG_TIMECODE) vbuf->timecode = b->timecode; } - return 0; }; static void vb2_warn_zero_bytesused(struct vb2_buffer *vb) @@ -176,7 +181,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be * returned to userspace */ -static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) +static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) { struct v4l2_buffer *b = pb; struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -191,7 +196,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) b->flags = vbuf->flags; b->field = vbuf->field; - b->timestamp = vbuf->timestamp; + b->timestamp = ns_to_timeval(vb->timestamp); b->timecode = vbuf->timecode; b->sequence = vbuf->sequence; b->reserved2 = 0; @@ -238,8 +243,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) */ b->flags &= ~V4L2_BUFFER_MASK_FLAGS; b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK; - if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) != - V4L2_BUF_FLAG_TIMESTAMP_COPY) { + if (!q->copy_timestamp) { /* * For non-COPY timestamps, drop timestamp source bits * and obtain the timestamp source from the queue. @@ -272,7 +276,10 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) if (vb2_buffer_in_use(q, vb)) b->flags |= V4L2_BUF_FLAG_MAPPED; - return 0; + if (!q->is_output && + b->flags & V4L2_BUF_FLAG_DONE && + b->flags & V4L2_BUF_FLAG_LAST) + q->last_buffer_dequeued = true; } /** @@ -308,8 +315,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, "for an output buffer\n"); return -EINVAL; } - vbuf->timestamp.tv_sec = 0; - vbuf->timestamp.tv_usec = 0; + vb->timestamp = 0; vbuf->sequence = 0; if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { @@ -404,8 +410,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, /* Zero flags that the vb2 core handles */ vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS; - if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) != - V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) { + if (!vb->vb2_queue->copy_timestamp || !V4L2_TYPE_IS_OUTPUT(b->type)) { /* * Non-COPY timestamps and non-OUTPUT queues will get * their timestamp and timestamp source flags from the @@ -434,7 +439,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, static const struct vb2_buf_ops v4l2_buf_ops = { .fill_user_buffer = __fill_v4l2_buffer, .fill_vb2_buffer = __fill_vb2_buffer, - .set_timestamp = __set_timestamp, + .copy_timestamp = __copy_timestamp, }; /** @@ -466,8 +471,9 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) } vb = q->bufs[b->index]; ret = __verify_planes_array(vb, b); - - return ret ? ret : vb2_core_querybuf(q, b->index, b); + if (!ret) + vb2_core_querybuf(q, b->index, b); + return ret; } EXPORT_SYMBOL(vb2_querybuf); @@ -525,14 +531,52 @@ EXPORT_SYMBOL_GPL(vb2_prepare_buf); */ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) { - int ret = vb2_verify_memory_type(q, create->memory, - create->format.type); + unsigned requested_planes = 1; + unsigned requested_sizes[VIDEO_MAX_PLANES]; + struct v4l2_format *f = &create->format; + int ret = vb2_verify_memory_type(q, create->memory, f->type); + unsigned i; create->index = q->num_buffers; if (create->count == 0) return ret != -EBUSY ? ret : 0; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + requested_planes = f->fmt.pix_mp.num_planes; + if (requested_planes == 0 || + requested_planes > VIDEO_MAX_PLANES) + return -EINVAL; + for (i = 0; i < requested_planes; i++) + requested_sizes[i] = + f->fmt.pix_mp.plane_fmt[i].sizeimage; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + requested_sizes[0] = f->fmt.pix.sizeimage; + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + requested_sizes[0] = f->fmt.vbi.samples_per_line * + (f->fmt.vbi.count[0] + f->fmt.vbi.count[1]); + break; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + requested_sizes[0] = f->fmt.sliced.io_size; + break; + case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: + requested_sizes[0] = f->fmt.sdr.buffersize; + break; + default: + return -EINVAL; + } + for (i = 0; i < requested_planes; i++) + if (requested_sizes[i] == 0) + return -EINVAL; return ret ? ret : vb2_core_create_bufs(q, create->memory, - &create->count, &create->format); + &create->count, requested_planes, requested_sizes); } EXPORT_SYMBOL_GPL(vb2_create_bufs); @@ -583,10 +627,6 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, ret = vb2_core_dqbuf(q, b, nonblocking); - if (!ret && !q->is_output && - b->flags & V4L2_BUF_FLAG_LAST) - q->last_buffer_dequeued = true; - return ret; } @@ -723,14 +763,13 @@ int vb2_queue_init(struct vb2_queue *q) q->buf_ops = &v4l2_buf_ops; q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type); q->is_output = V4L2_TYPE_IS_OUTPUT(q->type); + q->copy_timestamp = (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) + == V4L2_BUF_FLAG_TIMESTAMP_COPY; return vb2_core_queue_init(q); } EXPORT_SYMBOL_GPL(vb2_queue_init); -static int __vb2_init_fileio(struct vb2_queue *q, int read); -static int __vb2_cleanup_fileio(struct vb2_queue *q); - /** * vb2_queue_release() - stop streaming, release the queue and free memory * @q: videobuf2 queue @@ -741,7 +780,6 @@ static int __vb2_cleanup_fileio(struct vb2_queue *q); */ void vb2_queue_release(struct vb2_queue *q) { - __vb2_cleanup_fileio(q); vb2_core_queue_release(q); } EXPORT_SYMBOL_GPL(vb2_queue_release); @@ -769,9 +807,7 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) { struct video_device *vfd = video_devdata(file); unsigned long req_events = poll_requested_events(wait); - struct vb2_buffer *vb = NULL; unsigned int res = 0; - unsigned long flags; if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { struct v4l2_fh *fh = file->private_data; @@ -782,611 +818,18 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) poll_wait(file, &fh->wait, wait); } - if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM))) - return res; - if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM))) - return res; - - /* - * Start file I/O emulator only if streaming API has not been used yet. - */ - if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) { - if (!q->is_output && (q->io_modes & VB2_READ) && - (req_events & (POLLIN | POLLRDNORM))) { - if (__vb2_init_fileio(q, 1)) - return res | POLLERR; - } - if (q->is_output && (q->io_modes & VB2_WRITE) && - (req_events & (POLLOUT | POLLWRNORM))) { - if (__vb2_init_fileio(q, 0)) - return res | POLLERR; - /* - * Write to OUTPUT queue can be done immediately. - */ - return res | POLLOUT | POLLWRNORM; - } - } - - /* - * There is nothing to wait for if the queue isn't streaming, or if the - * error flag is set. - */ - if (!vb2_is_streaming(q) || q->error) - return res | POLLERR; /* * For compatibility with vb1: if QBUF hasn't been called yet, then * return POLLERR as well. This only affects capture queues, output * queues will always initialize waiting_for_buffers to false. */ - if (q->waiting_for_buffers) - return res | POLLERR; - - /* - * For output streams you can write as long as there are fewer buffers - * queued than there are buffers available. - */ - if (q->is_output && q->queued_count < q->num_buffers) - return res | POLLOUT | POLLWRNORM; - - if (list_empty(&q->done_list)) { - /* - * If the last buffer was dequeued from a capture queue, - * return immediately. DQBUF will return -EPIPE. - */ - if (q->last_buffer_dequeued) - return res | POLLIN | POLLRDNORM; - - poll_wait(file, &q->done_wq, wait); - } + if (q->waiting_for_buffers && (req_events & (POLLIN | POLLRDNORM))) + return POLLERR; - /* - * Take first buffer available for dequeuing. - */ - spin_lock_irqsave(&q->done_lock, flags); - if (!list_empty(&q->done_list)) - vb = list_first_entry(&q->done_list, struct vb2_buffer, - done_entry); - spin_unlock_irqrestore(&q->done_lock, flags); - - if (vb && (vb->state == VB2_BUF_STATE_DONE - || vb->state == VB2_BUF_STATE_ERROR)) { - return (q->is_output) ? - res | POLLOUT | POLLWRNORM : - res | POLLIN | POLLRDNORM; - } - return res; + return res | vb2_core_poll(q, file, wait); } EXPORT_SYMBOL_GPL(vb2_poll); -/** - * struct vb2_fileio_buf - buffer context used by file io emulator - * - * vb2 provides a compatibility layer and emulator of file io (read and - * write) calls on top of streaming API. This structure is used for - * tracking context related to the buffers. - */ -struct vb2_fileio_buf { - void *vaddr; - unsigned int size; - unsigned int pos; - 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 - * written to. If equal to q->num_buffers then a new buffer - * must be dequeued. - * @initial_index: in the read() case all buffers are queued up immediately - * in __vb2_init_fileio() and __vb2_perform_fileio() just cycles - * buffers. However, in the write() case no buffers are initially - * queued, instead whenever a buffer is full it is queued up by - * __vb2_perform_fileio(). Only once all available buffers have - * been queued up will __vb2_perform_fileio() start to dequeue - * buffers. This means that initially __vb2_perform_fileio() - * needs to know what buffer index to use when it is queuing up - * the buffers for the first time. That initial index is stored - * in this field. Once it is equal to q->num_buffers all - * available buffers have been queued and __vb2_perform_fileio() - * should start the normal dequeue/queue cycle. - * - * vb2 provides a compatibility layer and emulator of file io (read and - * write) calls on top of streaming API. For proper operation it required - * this structure to save the driver state between each call of the read - * or write function. - */ -struct vb2_fileio_data { - struct v4l2_requestbuffers req; - struct v4l2_plane p; - struct v4l2_buffer b; - struct vb2_fileio_buf bufs[VB2_MAX_FRAME]; - unsigned int cur_index; - unsigned int initial_index; - unsigned int q_count; - unsigned int dq_count; - unsigned read_once:1; - unsigned write_immediately:1; -}; - -/** - * __vb2_init_fileio() - initialize file io emulator - * @q: videobuf2 queue - * @read: mode selector (1 means read, 0 means write) - */ -static int __vb2_init_fileio(struct vb2_queue *q, int read) -{ - struct vb2_fileio_data *fileio; - int i, ret; - unsigned int count = 0; - - /* - * Sanity check - */ - if (WARN_ON((read && !(q->io_modes & VB2_READ)) || - (!read && !(q->io_modes & VB2_WRITE)))) - return -EINVAL; - - /* - * Check if device supports mapping buffers to kernel virtual space. - */ - if (!q->mem_ops->vaddr) - return -EBUSY; - - /* - * Check if streaming api has not been already activated. - */ - if (q->streaming || q->num_buffers > 0) - return -EBUSY; - - /* - * Start with count 1, driver can increase it in queue_setup() - */ - count = 1; - - dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n", - (read) ? "read" : "write", count, q->fileio_read_once, - q->fileio_write_immediately); - - fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL); - if (fileio == NULL) - return -ENOMEM; - - fileio->read_once = q->fileio_read_once; - fileio->write_immediately = q->fileio_write_immediately; - - /* - * Request buffers and use MMAP type to force driver - * to allocate buffers by itself. - */ - fileio->req.count = count; - fileio->req.memory = VB2_MEMORY_MMAP; - fileio->req.type = q->type; - q->fileio = fileio; - ret = vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count); - if (ret) - goto err_kfree; - - /* - * Check if plane_count is correct - * (multiplane buffers are not supported). - */ - if (q->bufs[0]->num_planes != 1) { - ret = -EBUSY; - goto err_reqbufs; - } - - /* - * Get kernel address of each buffer. - */ - for (i = 0; i < q->num_buffers; i++) { - fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0); - if (fileio->bufs[i].vaddr == NULL) { - ret = -EINVAL; - goto err_reqbufs; - } - fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0); - } - - /* - * Read mode requires pre queuing of all buffers. - */ - if (read) { - bool is_multiplanar = q->is_multiplanar; - - /* - * Queue all buffers. - */ - for (i = 0; i < q->num_buffers; i++) { - struct v4l2_buffer *b = &fileio->b; - - memset(b, 0, sizeof(*b)); - b->type = q->type; - if (is_multiplanar) { - memset(&fileio->p, 0, sizeof(fileio->p)); - b->m.planes = &fileio->p; - b->length = 1; - } - b->memory = q->memory; - b->index = i; - ret = vb2_internal_qbuf(q, b); - if (ret) - goto err_reqbufs; - fileio->bufs[i].queued = 1; - } - /* - * All buffers have been queued, so mark that by setting - * initial_index to q->num_buffers - */ - fileio->initial_index = q->num_buffers; - fileio->cur_index = q->num_buffers; - } - - /* - * Start streaming. - */ - ret = vb2_core_streamon(q, q->type); - if (ret) - goto err_reqbufs; - - return ret; - -err_reqbufs: - fileio->req.count = 0; - vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count); - -err_kfree: - q->fileio = NULL; - kfree(fileio); - return ret; -} - -/** - * __vb2_cleanup_fileio() - free resourced used by file io emulator - * @q: videobuf2 queue - */ -static int __vb2_cleanup_fileio(struct vb2_queue *q) -{ - struct vb2_fileio_data *fileio = q->fileio; - - if (fileio) { - vb2_core_streamoff(q, q->type); - q->fileio = NULL; - fileio->req.count = 0; - vb2_reqbufs(q, &fileio->req); - kfree(fileio); - dprintk(3, "file io emulator closed\n"); - } - return 0; -} - -/** - * __vb2_perform_fileio() - perform a single file io (read or write) operation - * @q: videobuf2 queue - * @data: pointed to target userspace buffer - * @count: number of bytes to read or write - * @ppos: file handle position tracking pointer - * @nonblock: mode selector (1 means blocking calls, 0 means nonblocking) - * @read: access mode selector (1 means read, 0 means write) - */ -static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count, - loff_t *ppos, int nonblock, int read) -{ - struct vb2_fileio_data *fileio; - struct vb2_fileio_buf *buf; - bool is_multiplanar = q->is_multiplanar; - /* - * When using write() to write data to an output video node the vb2 core - * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody - * else is able to provide this information with the write() operation. - */ - bool set_timestamp = !read && - (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == - V4L2_BUF_FLAG_TIMESTAMP_COPY; - int ret, index; - - dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n", - read ? "read" : "write", (long)*ppos, count, - nonblock ? "non" : ""); - - if (!data) - return -EINVAL; - - /* - * Initialize emulator on first call. - */ - if (!vb2_fileio_is_active(q)) { - ret = __vb2_init_fileio(q, read); - dprintk(3, "vb2_init_fileio result: %d\n", ret); - if (ret) - return ret; - } - fileio = q->fileio; - - /* - * Check if we need to dequeue the buffer. - */ - index = fileio->cur_index; - if (index >= q->num_buffers) { - /* - * Call vb2_dqbuf to get buffer back. - */ - memset(&fileio->b, 0, sizeof(fileio->b)); - fileio->b.type = q->type; - fileio->b.memory = q->memory; - if (is_multiplanar) { - memset(&fileio->p, 0, sizeof(fileio->p)); - fileio->b.m.planes = &fileio->p; - fileio->b.length = 1; - } - ret = vb2_internal_dqbuf(q, &fileio->b, nonblock); - dprintk(5, "vb2_dqbuf result: %d\n", ret); - if (ret) - return ret; - fileio->dq_count += 1; - - fileio->cur_index = index = fileio->b.index; - buf = &fileio->bufs[index]; - - /* - * Get number of bytes filled by the driver - */ - buf->pos = 0; - buf->queued = 0; - buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0) - : vb2_plane_size(q->bufs[index], 0); - /* Compensate for data_offset on read in the multiplanar case. */ - if (is_multiplanar && read && - fileio->b.m.planes[0].data_offset < buf->size) { - buf->pos = fileio->b.m.planes[0].data_offset; - buf->size -= buf->pos; - } - } else { - buf = &fileio->bufs[index]; - } - - /* - * Limit count on last few bytes of the buffer. - */ - if (buf->pos + count > buf->size) { - count = buf->size - buf->pos; - dprintk(5, "reducing read count: %zd\n", count); - } - - /* - * Transfer data to userspace. - */ - dprintk(3, "copying %zd bytes - buffer %d, offset %u\n", - count, index, buf->pos); - if (read) - ret = copy_to_user(data, buf->vaddr + buf->pos, count); - else - ret = copy_from_user(buf->vaddr + buf->pos, data, count); - if (ret) { - dprintk(3, "error copying data\n"); - return -EFAULT; - } - - /* - * Update counters. - */ - buf->pos += count; - *ppos += count; - - /* - * Queue next buffer if required. - */ - if (buf->pos == buf->size || (!read && fileio->write_immediately)) { - /* - * Check if this is the last buffer to read. - */ - if (read && fileio->read_once && fileio->dq_count == 1) { - dprintk(3, "read limit reached\n"); - return __vb2_cleanup_fileio(q); - } - - /* - * Call vb2_qbuf and give buffer to the driver. - */ - memset(&fileio->b, 0, sizeof(fileio->b)); - fileio->b.type = q->type; - fileio->b.memory = q->memory; - fileio->b.index = index; - fileio->b.bytesused = buf->pos; - if (is_multiplanar) { - memset(&fileio->p, 0, sizeof(fileio->p)); - fileio->p.bytesused = buf->pos; - fileio->b.m.planes = &fileio->p; - fileio->b.length = 1; - } - if (set_timestamp) - v4l2_get_timestamp(&fileio->b.timestamp); - ret = vb2_internal_qbuf(q, &fileio->b); - dprintk(5, "vb2_dbuf result: %d\n", ret); - if (ret) - return ret; - - /* - * Buffer has been queued, update the status - */ - buf->pos = 0; - buf->queued = 1; - buf->size = vb2_plane_size(q->bufs[index], 0); - fileio->q_count += 1; - /* - * If we are queuing up buffers for the first time, then - * increase initial_index by one. - */ - if (fileio->initial_index < q->num_buffers) - fileio->initial_index++; - /* - * The next buffer to use is either a buffer that's going to be - * queued for the first time (initial_index < q->num_buffers) - * or it is equal to q->num_buffers, meaning that the next - * time we need to dequeue a buffer since we've now queued up - * all the 'first time' buffers. - */ - fileio->cur_index = fileio->initial_index; - } - - /* - * Return proper number of bytes processed. - */ - if (ret == 0) - ret = count; - return ret; -} - -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count, - loff_t *ppos, int nonblocking) -{ - return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1); -} -EXPORT_SYMBOL_GPL(vb2_read); - -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count, - loff_t *ppos, int nonblocking) -{ - return __vb2_perform_fileio(q, (char __user *) data, count, - ppos, nonblocking, 0); -} -EXPORT_SYMBOL_GPL(vb2_write); - -struct vb2_threadio_data { - struct task_struct *thread; - vb2_thread_fnc fnc; - void *priv; - bool stop; -}; - -static int vb2_thread(void *data) -{ - struct vb2_queue *q = data; - struct vb2_threadio_data *threadio = q->threadio; - struct vb2_fileio_data *fileio = q->fileio; - bool set_timestamp = false; - int prequeue = 0; - int index = 0; - int ret = 0; - - if (q->is_output) { - prequeue = q->num_buffers; - set_timestamp = - (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == - V4L2_BUF_FLAG_TIMESTAMP_COPY; - } - - set_freezable(); - - for (;;) { - struct vb2_buffer *vb; - - /* - * Call vb2_dqbuf to get buffer back. - */ - memset(&fileio->b, 0, sizeof(fileio->b)); - fileio->b.type = q->type; - fileio->b.memory = q->memory; - if (prequeue) { - fileio->b.index = index++; - prequeue--; - } else { - call_void_qop(q, wait_finish, q); - if (!threadio->stop) - ret = vb2_internal_dqbuf(q, &fileio->b, 0); - call_void_qop(q, wait_prepare, q); - dprintk(5, "file io: vb2_dqbuf result: %d\n", ret); - } - if (ret || threadio->stop) - break; - try_to_freeze(); - - vb = q->bufs[fileio->b.index]; - if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR)) - if (threadio->fnc(vb, threadio->priv)) - break; - call_void_qop(q, wait_finish, q); - if (set_timestamp) - v4l2_get_timestamp(&fileio->b.timestamp); - if (!threadio->stop) - ret = vb2_internal_qbuf(q, &fileio->b); - call_void_qop(q, wait_prepare, q); - if (ret || threadio->stop) - break; - } - - /* Hmm, linux becomes *very* unhappy without this ... */ - while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - } - return 0; -} - -/* - * This function should not be used for anything else but the videobuf2-dvb - * support. If you think you have another good use-case for this, then please - * contact the linux-media mailinglist first. - */ -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv, - const char *thread_name) -{ - struct vb2_threadio_data *threadio; - int ret = 0; - - if (q->threadio) - return -EBUSY; - if (vb2_is_busy(q)) - return -EBUSY; - if (WARN_ON(q->fileio)) - return -EBUSY; - - threadio = kzalloc(sizeof(*threadio), GFP_KERNEL); - if (threadio == NULL) - return -ENOMEM; - threadio->fnc = fnc; - threadio->priv = priv; - - ret = __vb2_init_fileio(q, !q->is_output); - dprintk(3, "file io: vb2_init_fileio result: %d\n", ret); - if (ret) - goto nomem; - q->threadio = threadio; - threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name); - if (IS_ERR(threadio->thread)) { - ret = PTR_ERR(threadio->thread); - threadio->thread = NULL; - goto nothread; - } - return 0; - -nothread: - __vb2_cleanup_fileio(q); -nomem: - kfree(threadio); - return ret; -} -EXPORT_SYMBOL_GPL(vb2_thread_start); - -int vb2_thread_stop(struct vb2_queue *q) -{ - struct vb2_threadio_data *threadio = q->threadio; - int err; - - if (threadio == NULL) - return 0; - threadio->stop = true; - /* Wake up all pending sleeps in the thread */ - vb2_queue_error(q); - err = kthread_stop(threadio->thread); - __vb2_cleanup_fileio(q); - threadio->thread = NULL; - kfree(threadio); - q->threadio = NULL; - return err; -} -EXPORT_SYMBOL_GPL(vb2_thread_stop); - /* * The following functions are not part of the vb2 core API, but are helper * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations @@ -1440,8 +883,8 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv, return res; if (vb2_queue_is_busy(vdev, file)) return -EBUSY; - res = vb2_core_create_bufs(vdev->queue, p->memory, &p->count, - &p->format); + + res = vb2_create_bufs(vdev->queue, p); if (res == 0) vdev->queue->owner = file->private_data; return res; |