diff options
Diffstat (limited to 'drivers/media')
220 files changed, 6819 insertions, 5081 deletions
diff --git a/drivers/media/dvb-core/demux.h b/drivers/media/dvb-core/demux.h index 833191bcd810..ccc1f43cb9a9 100644 --- a/drivers/media/dvb-core/demux.h +++ b/drivers/media/dvb-core/demux.h @@ -32,9 +32,9 @@ #include <linux/time.h> #include <linux/dvb/dmx.h> -/*--------------------------------------------------------------------------*/ -/* Common definitions */ -/*--------------------------------------------------------------------------*/ +/* + * Common definitions + */ /* * DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter. @@ -45,7 +45,8 @@ #endif /* - * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter. + * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed + * filter. */ #ifndef DMX_MAX_SECTION_SIZE @@ -55,139 +56,296 @@ #define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188) #endif - /* - * enum dmx_success: Success codes for the Demux Callback API. + * TS packet reception */ -enum dmx_success { - DMX_OK = 0, /* Received Ok */ - DMX_LENGTH_ERROR, /* Incorrect length */ - DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */ - DMX_CRC_ERROR, /* Incorrect CRC */ - DMX_FRAME_ERROR, /* Frame alignment error */ - DMX_FIFO_ERROR, /* Receiver FIFO overrun */ - DMX_MISSED_ERROR /* Receiver missed packet */ -} ; - -/*--------------------------------------------------------------------------*/ -/* TS packet reception */ -/*--------------------------------------------------------------------------*/ - -/* TS filter type for set() */ - -#define TS_PACKET 1 /* send TS packets (188 bytes) to callback (default) */ -#define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS - payload (<=184 bytes per packet) to callback */ -#define TS_DECODER 4 /* send stream to built-in decoder (if present) */ -#define TS_DEMUX 8 /* in case TS_PACKET is set, send the TS to - the demux device, not to the dvr device */ +/** + * enum ts_filter_type - filter type bitmap for dmx_ts_feed.set() + * + * @TS_PACKET: Send TS packets (188 bytes) to callback (default). + * @TS_PAYLOAD_ONLY: In case TS_PACKET is set, only send the TS payload + * (<=184 bytes per packet) to callback + * @TS_DECODER: Send stream to built-in decoder (if present). + * @TS_DEMUX: In case TS_PACKET is set, send the TS to the demux + * device, not to the dvr device + */ +enum ts_filter_type { + TS_PACKET = 1, + TS_PAYLOAD_ONLY = 2, + TS_DECODER = 4, + TS_DEMUX = 8, +}; +/** + * struct dmx_ts_feed - Structure that contains a TS feed filter + * + * @is_filtering: Set to non-zero when filtering in progress + * @parent: pointer to struct dmx_demux + * @priv: pointer to private data of the API client + * @set: sets the TS filter + * @start_filtering: starts TS filtering + * @stop_filtering: stops TS filtering + * + * A TS feed is typically mapped to a hardware PID filter on the demux chip. + * Using this API, the client can set the filtering properties to start/stop + * filtering TS packets on a particular TS feed. + */ struct dmx_ts_feed { - int is_filtering; /* Set to non-zero when filtering in progress */ - struct dmx_demux *parent; /* Back-pointer */ - void *priv; /* Pointer to private data of the API client */ - int (*set) (struct dmx_ts_feed *feed, - u16 pid, - int type, - enum dmx_ts_pes pes_type, - size_t circular_buffer_size, - struct timespec timeout); - int (*start_filtering) (struct dmx_ts_feed* feed); - int (*stop_filtering) (struct dmx_ts_feed* feed); + int is_filtering; + struct dmx_demux *parent; + void *priv; + int (*set)(struct dmx_ts_feed *feed, + u16 pid, + int type, + enum dmx_ts_pes pes_type, + size_t circular_buffer_size, + struct timespec timeout); + int (*start_filtering)(struct dmx_ts_feed *feed); + int (*stop_filtering)(struct dmx_ts_feed *feed); }; -/*--------------------------------------------------------------------------*/ -/* Section reception */ -/*--------------------------------------------------------------------------*/ +/* + * Section reception + */ +/** + * struct dmx_section_filter - Structure that describes a section filter + * + * @filter_value: Contains up to 16 bytes (128 bits) of the TS section header + * that will be matched by the section filter + * @filter_mask: Contains a 16 bytes (128 bits) filter mask with the bits + * specified by @filter_value that will be used on the filter + * match logic. + * @filter_mode: Contains a 16 bytes (128 bits) filter mode. + * @parent: Pointer to struct dmx_section_feed. + * @priv: Pointer to private data of the API client. + * + * + * The @filter_mask controls which bits of @filter_value are compared with + * the section headers/payload. On a binary value of 1 in filter_mask, the + * corresponding bits are compared. The filter only accepts sections that are + * equal to filter_value in all the tested bit positions. + */ struct dmx_section_filter { - u8 filter_value [DMX_MAX_FILTER_SIZE]; - u8 filter_mask [DMX_MAX_FILTER_SIZE]; - u8 filter_mode [DMX_MAX_FILTER_SIZE]; - struct dmx_section_feed* parent; /* Back-pointer */ - void* priv; /* Pointer to private data of the API client */ + u8 filter_value[DMX_MAX_FILTER_SIZE]; + u8 filter_mask[DMX_MAX_FILTER_SIZE]; + u8 filter_mode[DMX_MAX_FILTER_SIZE]; + struct dmx_section_feed *parent; /* Back-pointer */ + void *priv; /* Pointer to private data of the API client */ }; +/** + * struct dmx_section_feed - Structure that contains a section feed filter + * + * @is_filtering: Set to non-zero when filtering in progress + * @parent: pointer to struct dmx_demux + * @priv: pointer to private data of the API client + * @check_crc: If non-zero, check the CRC values of filtered sections. + * @set: sets the section filter + * @allocate_filter: This function is used to allocate a section filter on + * the demux. It should only be called when no filtering + * is in progress on this section feed. If a filter cannot + * be allocated, the function fails with -ENOSPC. + * @release_filter: This function releases all the resources of a + * previously allocated section filter. The function + * should not be called while filtering is in progress + * on this section feed. After calling this function, + * the caller should not try to dereference the filter + * pointer. + * @start_filtering: starts section filtering + * @stop_filtering: stops section filtering + * + * A TS feed is typically mapped to a hardware PID filter on the demux chip. + * Using this API, the client can set the filtering properties to start/stop + * filtering TS packets on a particular TS feed. + */ struct dmx_section_feed { - int is_filtering; /* Set to non-zero when filtering in progress */ - struct dmx_demux* parent; /* Back-pointer */ - void* priv; /* Pointer to private data of the API client */ + int is_filtering; + struct dmx_demux *parent; + void *priv; int check_crc; + + /* private: Used internally at dvb_demux.c */ u32 crc_val; u8 *secbuf; u8 secbuf_base[DMX_MAX_SECFEED_SIZE]; u16 secbufp, seclen, tsfeedp; - int (*set) (struct dmx_section_feed* feed, - u16 pid, - size_t circular_buffer_size, - int check_crc); - int (*allocate_filter) (struct dmx_section_feed* feed, - struct dmx_section_filter** filter); - int (*release_filter) (struct dmx_section_feed* feed, - struct dmx_section_filter* filter); - int (*start_filtering) (struct dmx_section_feed* feed); - int (*stop_filtering) (struct dmx_section_feed* feed); + /* public: */ + int (*set)(struct dmx_section_feed *feed, + u16 pid, + size_t circular_buffer_size, + int check_crc); + int (*allocate_filter)(struct dmx_section_feed *feed, + struct dmx_section_filter **filter); + int (*release_filter)(struct dmx_section_feed *feed, + struct dmx_section_filter *filter); + int (*start_filtering)(struct dmx_section_feed *feed); + int (*stop_filtering)(struct dmx_section_feed *feed); }; -/*--------------------------------------------------------------------------*/ -/* Callback functions */ -/*--------------------------------------------------------------------------*/ - -typedef int (*dmx_ts_cb) ( const u8 * buffer1, - size_t buffer1_length, - const u8 * buffer2, - size_t buffer2_length, - struct dmx_ts_feed* source, - enum dmx_success success); +/* + * Callback functions + */ -typedef int (*dmx_section_cb) ( const u8 * buffer1, - size_t buffer1_len, - const u8 * buffer2, - size_t buffer2_len, - struct dmx_section_filter * source, - enum dmx_success success); +/** + * typedef dmx_ts_cb - DVB demux TS filter callback function prototype + * + * @buffer1: Pointer to the start of the filtered TS packets. + * @buffer1_length: Length of the TS data in buffer1. + * @buffer2: Pointer to the tail of the filtered TS packets, or NULL. + * @buffer2_length: Length of the TS data in buffer2. + * @source: Indicates which TS feed is the source of the callback. + * + * This function callback prototype, provided by the client of the demux API, + * is called from the demux code. The function is only called when filtering + * on ae TS feed has been enabled using the start_filtering() function at + * the &dmx_demux. + * Any TS packets that match the filter settings are copied to a circular + * buffer. The filtered TS packets are delivered to the client using this + * callback function. The size of the circular buffer is controlled by the + * circular_buffer_size parameter of the &dmx_ts_feed.@set function. + * It is expected that the @buffer1 and @buffer2 callback parameters point to + * addresses within the circular buffer, but other implementations are also + * possible. Note that the called party should not try to free the memory + * the @buffer1 and @buffer2 parameters point to. + * + * When this function is called, the @buffer1 parameter typically points to + * the start of the first undelivered TS packet within a circular buffer. + * The @buffer2 buffer parameter is normally NULL, except when the received + * TS packets have crossed the last address of the circular buffer and + * ”wrapped” to the beginning of the buffer. In the latter case the @buffer1 + * parameter would contain an address within the circular buffer, while the + * @buffer2 parameter would contain the first address of the circular buffer. + * The number of bytes delivered with this function (i.e. @buffer1_length + + * @buffer2_length) is usually equal to the value of callback_length parameter + * given in the set() function, with one exception: if a timeout occurs before + * receiving callback_length bytes of TS data, any undelivered packets are + * immediately delivered to the client by calling this function. The timeout + * duration is controlled by the set() function in the TS Feed API. + * + * If a TS packet is received with errors that could not be fixed by the + * TS-level forward error correction (FEC), the Transport_error_indicator + * flag of the TS packet header should be set. The TS packet should not be + * discarded, as the error can possibly be corrected by a higher layer + * protocol. If the called party is slow in processing the callback, it + * is possible that the circular buffer eventually fills up. If this happens, + * the demux driver should discard any TS packets received while the buffer + * is full and return -EOVERFLOW. + * + * The type of data returned to the callback can be selected by the + * &dmx_ts_feed.@set function. The type parameter decides if the raw + * TS packet (TS_PACKET) or just the payload (TS_PACKET|TS_PAYLOAD_ONLY) + * should be returned. If additionally the TS_DECODER bit is set the stream + * will also be sent to the hardware MPEG decoder. + * + * Return: + * 0, on success; + * -EOVERFLOW, on buffer overflow. + */ +typedef int (*dmx_ts_cb)(const u8 *buffer1, + size_t buffer1_length, + const u8 *buffer2, + size_t buffer2_length, + struct dmx_ts_feed *source); + +/** + * typedef dmx_section_cb - DVB demux TS filter callback function prototype + * + * @buffer1: Pointer to the start of the filtered section, e.g. + * within the circular buffer of the demux driver. + * @buffer1_len: Length of the filtered section data in @buffer1, + * including headers and CRC. + * @buffer2: Pointer to the tail of the filtered section data, + * or NULL. Useful to handle the wrapping of a + * circular buffer. + * @buffer2_len: Length of the filtered section data in @buffer2, + * including headers and CRC. + * @source: Indicates which section feed is the source of the + * callback. + * + * This function callback prototype, provided by the client of the demux API, + * is called from the demux code. The function is only called when + * filtering of sections has been enabled using the function + * &dmx_ts_feed.@start_filtering. When the demux driver has received a + * complete section that matches at least one section filter, the client + * is notified via this callback function. Normally this function is called + * for each received section; however, it is also possible to deliver + * multiple sections with one callback, for example when the system load + * is high. If an error occurs while receiving a section, this + * function should be called with the corresponding error type set in the + * success field, whether or not there is data to deliver. The Section Feed + * implementation should maintain a circular buffer for received sections. + * However, this is not necessary if the Section Feed API is implemented as + * a client of the TS Feed API, because the TS Feed implementation then + * buffers the received data. The size of the circular buffer can be + * configured using the &dmx_ts_feed.@set function in the Section Feed API. + * If there is no room in the circular buffer when a new section is received, + * the section must be discarded. If this happens, the value of the success + * parameter should be DMX_OVERRUN_ERROR on the next callback. + */ +typedef int (*dmx_section_cb)(const u8 *buffer1, + size_t buffer1_len, + const u8 *buffer2, + size_t buffer2_len, + struct dmx_section_filter *source); /*--------------------------------------------------------------------------*/ /* DVB Front-End */ /*--------------------------------------------------------------------------*/ +/** + * enum dmx_frontend_source - Used to identify the type of frontend + * + * @DMX_MEMORY_FE: The source of the demux is memory. It means that + * the MPEG-TS to be filtered comes from userspace, + * via write() syscall. + * + * @DMX_FRONTEND_0: The source of the demux is a frontend connected + * to the demux. + */ enum dmx_frontend_source { DMX_MEMORY_FE, DMX_FRONTEND_0, - DMX_FRONTEND_1, - DMX_FRONTEND_2, - DMX_FRONTEND_3, - DMX_STREAM_0, /* external stream input, e.g. LVDS */ - DMX_STREAM_1, - DMX_STREAM_2, - DMX_STREAM_3 }; +/** + * struct dmx_frontend - Structure that lists the frontends associated with + * a demux + * + * @connectivity_list: List of front-ends that can be connected to a + * particular demux; + * @source: Type of the frontend. + * + * FIXME: this structure should likely be replaced soon by some + * media-controller based logic. + */ struct dmx_frontend { - struct list_head connectivity_list; /* List of front-ends that can - be connected to a particular - demux */ + struct list_head connectivity_list; enum dmx_frontend_source source; }; -/*--------------------------------------------------------------------------*/ -/* MPEG-2 TS Demux */ -/*--------------------------------------------------------------------------*/ - /* - * Flags OR'ed in the capabilities field of struct dmx_demux. + * MPEG-2 TS Demux */ -#define DMX_TS_FILTERING 1 -#define DMX_PES_FILTERING 2 -#define DMX_SECTION_FILTERING 4 -#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */ -#define DMX_CRC_CHECKING 16 -#define DMX_TS_DESCRAMBLING 32 +/** + * enum dmx_demux_caps - MPEG-2 TS Demux capabilities bitmap + * + * @DMX_TS_FILTERING: set if TS filtering is supported; + * @DMX_SECTION_FILTERING: set if section filtering is supported; + * @DMX_MEMORY_BASED_FILTERING: set if write() available. + * + * Those flags are OR'ed in the &dmx_demux.&capabilities field + */ +enum dmx_demux_caps { + DMX_TS_FILTERING = 1, + DMX_SECTION_FILTERING = 4, + DMX_MEMORY_BASED_FILTERING = 8, +}; /* * Demux resource type identifier. @@ -200,42 +358,241 @@ struct dmx_frontend { *. */ -#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list) +#define DMX_FE_ENTRY(list) \ + list_entry(list, struct dmx_frontend, connectivity_list) + +/** + * struct dmx_demux - Structure that contains the demux capabilities and + * callbacks. + * + * @capabilities: Bitfield of capability flags. + * + * @frontend: Front-end connected to the demux + * + * @priv: Pointer to private data of the API client + * + * @open: This function reserves the demux for use by the caller and, if + * necessary, initializes the demux. When the demux is no longer needed, + * the function @close should be called. It should be possible for + * multiple clients to access the demux at the same time. Thus, the + * function implementation should increment the demux usage count when + * @open is called and decrement it when @close is called. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * It returns + * 0 on success; + * -EUSERS, if maximum usage count was reached; + * -EINVAL, on bad parameter. + * + * @close: This function reserves the demux for use by the caller and, if + * necessary, initializes the demux. When the demux is no longer needed, + * the function @close should be called. It should be possible for + * multiple clients to access the demux at the same time. Thus, the + * function implementation should increment the demux usage count when + * @open is called and decrement it when @close is called. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * It returns + * 0 on success; + * -ENODEV, if demux was not in use (e. g. no users); + * -EINVAL, on bad parameter. + * + * @write: This function provides the demux driver with a memory buffer + * containing TS packets. Instead of receiving TS packets from the DVB + * front-end, the demux driver software will read packets from memory. + * Any clients of this demux with active TS, PES or Section filters will + * receive filtered data via the Demux callback API (see 0). The function + * returns when all the data in the buffer has been consumed by the demux. + * Demux hardware typically cannot read TS from memory. If this is the + * case, memory-based filtering has to be implemented entirely in software. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * The @buf function parameter contains a pointer to the TS data in + * kernel-space memory. + * The @count function parameter contains the length of the TS data. + * It returns + * 0 on success; + * -ERESTARTSYS, if mutex lock was interrupted; + * -EINTR, if a signal handling is pending; + * -ENODEV, if demux was removed; + * -EINVAL, on bad parameter. + * + * @allocate_ts_feed: Allocates a new TS feed, which is used to filter the TS + * packets carrying a certain PID. The TS feed normally corresponds to a + * hardware PID filter on the demux chip. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * The @feed function parameter contains a pointer to the TS feed API and + * instance data. + * The @callback function parameter contains a pointer to the callback + * function for passing received TS packet. + * It returns + * 0 on success; + * -ERESTARTSYS, if mutex lock was interrupted; + * -EBUSY, if no more TS feeds is available; + * -EINVAL, on bad parameter. + * + * @release_ts_feed: Releases the resources allocated with @allocate_ts_feed. + * Any filtering in progress on the TS feed should be stopped before + * calling this function. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * The @feed function parameter contains a pointer to the TS feed API and + * instance data. + * It returns + * 0 on success; + * -EINVAL on bad parameter. + * + * @allocate_section_feed: Allocates a new section feed, i.e. a demux resource + * for filtering and receiving sections. On platforms with hardware + * support for section filtering, a section feed is directly mapped to + * the demux HW. On other platforms, TS packets are first PID filtered in + * hardware and a hardware section filter then emulated in software. The + * caller obtains an API pointer of type dmx_section_feed_t as an out + * parameter. Using this API the caller can set filtering parameters and + * start receiving sections. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * The @feed function parameter contains a pointer to the TS feed API and + * instance data. + * The @callback function parameter contains a pointer to the callback + * function for passing received TS packet. + * It returns + * 0 on success; + * -EBUSY, if no more TS feeds is available; + * -EINVAL, on bad parameter. + * + * @release_section_feed: Releases the resources allocated with + * @allocate_section_feed, including allocated filters. Any filtering in + * progress on the section feed should be stopped before calling this + * function. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * The @feed function parameter contains a pointer to the TS feed API and + * instance data. + * It returns + * 0 on success; + * -EINVAL, on bad parameter. + * + * @add_frontend: Registers a connectivity between a demux and a front-end, + * i.e., indicates that the demux can be connected via a call to + * @connect_frontend to use the given front-end as a TS source. The + * client of this function has to allocate dynamic or static memory for + * the frontend structure and initialize its fields before calling this + * function. This function is normally called during the driver + * initialization. The caller must not free the memory of the frontend + * struct before successfully calling @remove_frontend. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * The @frontend function parameter contains a pointer to the front-end + * instance data. + * It returns + * 0 on success; + * -EINVAL, on bad parameter. + * + * @remove_frontend: Indicates that the given front-end, registered by a call + * to @add_frontend, can no longer be connected as a TS source by this + * demux. The function should be called when a front-end driver or a demux + * driver is removed from the system. If the front-end is in use, the + * function fails with the return value of -EBUSY. After successfully + * calling this function, the caller can free the memory of the frontend + * struct if it was dynamically allocated before the @add_frontend + * operation. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * The @frontend function parameter contains a pointer to the front-end + * instance data. + * It returns + * 0 on success; + * -ENODEV, if the front-end was not found, + * -EINVAL, on bad parameter. + * + * @get_frontends: Provides the APIs of the front-ends that have been + * registered for this demux. Any of the front-ends obtained with this + * call can be used as a parameter for @connect_frontend. The include + * file demux.h contains the macro DMX_FE_ENTRY() for converting an + * element of the generic type struct &list_head * to the type + * struct &dmx_frontend *. The caller must not free the memory of any of + * the elements obtained via this function call. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * It returns a struct list_head pointer to the list of front-end + * interfaces, or NULL in the case of an empty list. + * + * @connect_frontend: Connects the TS output of the front-end to the input of + * the demux. A demux can only be connected to a front-end registered to + * the demux with the function @add_frontend. It may or may not be + * possible to connect multiple demuxes to the same front-end, depending + * on the capabilities of the HW platform. When not used, the front-end + * should be released by calling @disconnect_frontend. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * The @frontend function parameter contains a pointer to the front-end + * instance data. + * It returns + * 0 on success; + * -EINVAL, on bad parameter. + * + * @disconnect_frontend: Disconnects the demux and a front-end previously + * connected by a @connect_frontend call. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * It returns + * 0 on success; + * -EINVAL on bad parameter. + * + * @get_pes_pids: Get the PIDs for DMX_PES_AUDIO0, DMX_PES_VIDEO0, + * DMX_PES_TELETEXT0, DMX_PES_SUBTITLE0 and DMX_PES_PCR0. + * The @demux function parameter contains a pointer to the demux API and + * instance data. + * The @pids function parameter contains an array with five u16 elements + * where the PIDs will be stored. + * It returns + * 0 on success; + * -EINVAL on bad parameter. + */ struct dmx_demux { - u32 capabilities; /* Bitfield of capability flags */ - struct dmx_frontend* frontend; /* Front-end connected to the demux */ - void* priv; /* Pointer to private data of the API client */ - int (*open) (struct dmx_demux* demux); - int (*close) (struct dmx_demux* demux); - int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count); - int (*allocate_ts_feed) (struct dmx_demux* demux, - struct dmx_ts_feed** feed, - dmx_ts_cb callback); - int (*release_ts_feed) (struct dmx_demux* demux, - struct dmx_ts_feed* feed); - int (*allocate_section_feed) (struct dmx_demux* demux, - struct dmx_section_feed** feed, - dmx_section_cb callback); - int (*release_section_feed) (struct dmx_demux* demux, - struct dmx_section_feed* feed); - int (*add_frontend) (struct dmx_demux* demux, - struct dmx_frontend* frontend); - int (*remove_frontend) (struct dmx_demux* demux, - struct dmx_frontend* frontend); - struct list_head* (*get_frontends) (struct dmx_demux* demux); - int (*connect_frontend) (struct dmx_demux* demux, - struct dmx_frontend* frontend); - int (*disconnect_frontend) (struct dmx_demux* demux); - - int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids); - - int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps); - - int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src); - - int (*get_stc) (struct dmx_demux* demux, unsigned int num, - u64 *stc, unsigned int *base); + enum dmx_demux_caps capabilities; + struct dmx_frontend *frontend; + void *priv; + int (*open)(struct dmx_demux *demux); + int (*close)(struct dmx_demux *demux); + int (*write)(struct dmx_demux *demux, const char __user *buf, + size_t count); + int (*allocate_ts_feed)(struct dmx_demux *demux, + struct dmx_ts_feed **feed, + dmx_ts_cb callback); + int (*release_ts_feed)(struct dmx_demux *demux, + struct dmx_ts_feed *feed); + int (*allocate_section_feed)(struct dmx_demux *demux, + struct dmx_section_feed **feed, + dmx_section_cb callback); + int (*release_section_feed)(struct dmx_demux *demux, + struct dmx_section_feed *feed); + int (*add_frontend)(struct dmx_demux *demux, + struct dmx_frontend *frontend); + int (*remove_frontend)(struct dmx_demux *demux, + struct dmx_frontend *frontend); + struct list_head *(*get_frontends)(struct dmx_demux *demux); + int (*connect_frontend)(struct dmx_demux *demux, + struct dmx_frontend *frontend); + int (*disconnect_frontend)(struct dmx_demux *demux); + + int (*get_pes_pids)(struct dmx_demux *demux, u16 *pids); + + /* private: Not used upstream and never documented */ +#if 0 + int (*get_caps)(struct dmx_demux *demux, struct dmx_caps *caps); + int (*set_source)(struct dmx_demux *demux, const dmx_source_t *src); +#endif + /* + * private: Only used at av7110, to read some data from firmware. + * As this was never documented, we have no clue about what's + * there, and its usage on other drivers aren't encouraged. + */ + int (*get_stc)(struct dmx_demux *demux, unsigned int num, + u64 *stc, unsigned int *base); }; #endif /* #ifndef __DEMUX_H */ diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index d0e3f9d85f34..ea9abde902e9 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -352,8 +352,7 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - struct dmx_section_filter *filter, - enum dmx_success success) + struct dmx_section_filter *filter) { struct dmxdev_filter *dmxdevfilter = filter->priv; int ret; @@ -386,8 +385,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - struct dmx_ts_feed *feed, - enum dmx_success success) + struct dmx_ts_feed *feed) { struct dmxdev_filter *dmxdevfilter = feed->priv; struct dvb_ringbuffer *buffer; @@ -1023,6 +1021,9 @@ static int dvb_demux_do_ioctl(struct file *file, dmxdev->demux->get_pes_pids(dmxdev->demux, parg); break; +#if 0 + /* Not used upstream and never documented */ + case DMX_GET_CAPS: if (!dmxdev->demux->get_caps) { ret = -EINVAL; @@ -1038,6 +1039,7 @@ static int dvb_demux_do_ioctl(struct file *file, } ret = dmxdev->demux->set_source(dmxdev->demux, parg); break; +#endif case DMX_GET_STC: if (!dmxdev->demux->get_stc) { diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index c117fb3b4aff..0a46580b5376 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -257,6 +257,7 @@ #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab #define USB_PID_TERRATEC_H7 0x10b4 #define USB_PID_TERRATEC_H7_2 0x10a3 +#define USB_PID_TERRATEC_H7_3 0x10a5 #define USB_PID_TERRATEC_T3 0x10a0 #define USB_PID_TERRATEC_T5 0x10a1 #define USB_PID_NOXON_DAB_STICK 0x00b3 diff --git a/drivers/media/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb-core/dvb_ca_en50221.h index aba3b4fbd704..1e4bbbd34d91 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.h +++ b/drivers/media/dvb-core/dvb_ca_en50221.h @@ -12,10 +12,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _DVB_CA_EN50221_H_ @@ -37,50 +33,53 @@ #define DVB_CA_EN50221_CAMCHANGE_REMOVED 0 #define DVB_CA_EN50221_CAMCHANGE_INSERTED 1 - - -/* Structure describing a CA interface */ +/** + * struct dvb_ca_en50221- Structure describing a CA interface + * + * @owner: the module owning this structure + * @read_attribute_mem: function for reading attribute memory on the CAM + * @write_attribute_mem: function for writing attribute memory on the CAM + * @read_cam_control: function for reading the control interface on the CAM + * @write_cam_control: function for reading the control interface on the CAM + * @slot_reset: function to reset the CAM slot + * @slot_shutdown: function to shutdown a CAM slot + * @slot_ts_enable: function to enable the Transport Stream on a CAM slot + * @poll_slot_status: function to poll slot status. Only necessary if + * DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set. + * @data: private data, used by caller. + * @private: Opaque data used by the dvb_ca core. Do not modify! + * + * NOTE: the read_*, write_* and poll_slot_status functions will be + * called for different slots concurrently and need to use locks where + * and if appropriate. There will be no concurrent access to one slot. + */ struct dvb_ca_en50221 { + struct module *owner; - /* the module owning this structure */ - struct module* owner; - - /* NOTE: the read_*, write_* and poll_slot_status functions will be - * called for different slots concurrently and need to use locks where - * and if appropriate. There will be no concurrent access to one slot. - */ + int (*read_attribute_mem)(struct dvb_ca_en50221 *ca, + int slot, int address); + int (*write_attribute_mem)(struct dvb_ca_en50221 *ca, + int slot, int address, u8 value); - /* functions for accessing attribute memory on the CAM */ - int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); - int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value); + int (*read_cam_control)(struct dvb_ca_en50221 *ca, + int slot, u8 address); + int (*write_cam_control)(struct dvb_ca_en50221 *ca, + int slot, u8 address, u8 value); - /* functions for accessing the control interface on the CAM */ - int (*read_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address); - int (*write_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value); + int (*slot_reset)(struct dvb_ca_en50221 *ca, int slot); + int (*slot_shutdown)(struct dvb_ca_en50221 *ca, int slot); + int (*slot_ts_enable)(struct dvb_ca_en50221 *ca, int slot); - /* Functions for controlling slots */ - int (*slot_reset)(struct dvb_ca_en50221* ca, int slot); - int (*slot_shutdown)(struct dvb_ca_en50221* ca, int slot); - int (*slot_ts_enable)(struct dvb_ca_en50221* ca, int slot); + int (*poll_slot_status)(struct dvb_ca_en50221 *ca, int slot, int open); - /* - * Poll slot status. - * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set - */ - int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open); + void *data; - /* private data, used by caller */ - void* data; - - /* Opaque data used by the dvb_ca core. Do not modify! */ - void* private; + void *private; }; - - - -/* ******************************************************************************** */ -/* Functions for reporting IRQ events */ +/* + * Functions for reporting IRQ events + */ /** * dvb_ca_en50221_camchange_irq - A CAMCHANGE IRQ has occurred. @@ -89,7 +88,8 @@ struct dvb_ca_en50221 { * @slot: Slot concerned. * @change_type: One of the DVB_CA_CAMCHANGE_* values */ -void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type); +void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221 *pubca, int slot, + int change_type); /** * dvb_ca_en50221_camready_irq - A CAMREADY IRQ has occurred. @@ -97,7 +97,7 @@ void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int ch * @pubca: CA instance. * @slot: Slot concerned. */ -void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot); +void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot); /** * dvb_ca_en50221_frda_irq - An FR or a DA IRQ has occurred. @@ -105,12 +105,11 @@ void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot); * @ca: CA instance. * @slot: Slot concerned. */ -void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot); - +void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *ca, int slot); - -/* ******************************************************************************** */ -/* Initialisation/shutdown functions */ +/* + * Initialisation/shutdown functions + */ /** * dvb_ca_en50221_init - Initialise a new DVB CA device. @@ -122,15 +121,15 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot); * * @return 0 on success, nonzero on failure */ -extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca, int flags, int slot_count); +extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, + struct dvb_ca_en50221 *ca, int flags, + int slot_count); /** * dvb_ca_en50221_release - Release a DVB CA device. * * @ca: The associated dvb_ca instance. */ -extern void dvb_ca_en50221_release(struct dvb_ca_en50221* ca); - - +extern void dvb_ca_en50221_release(struct dvb_ca_en50221 *ca); #endif diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c index 6c7ff0cdcd32..0cc5e935166c 100644 --- a/drivers/media/dvb-core/dvb_demux.c +++ b/drivers/media/dvb-core/dvb_demux.c @@ -130,7 +130,7 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed, feed->peslen += count; - return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK); + return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts); } static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, @@ -152,7 +152,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, return 0; return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen, - NULL, 0, &f->filter, DMX_OK); + NULL, 0, &f->filter); } static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed) @@ -367,8 +367,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, if (feed->ts_type & TS_PAYLOAD_ONLY) dvb_dmx_swfilter_payload(feed, buf); else - feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, - DMX_OK); + feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts); } if (feed->ts_type & TS_DECODER) if (feed->demux->write_to_decoder) @@ -469,7 +468,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) if (feed->pid == pid) dvb_dmx_swfilter_packet_type(feed, buf); else if (feed->pid == 0x2000) - feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); + feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts); } } @@ -588,7 +587,7 @@ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count) spin_lock_irqsave(&demux->lock, flags); - demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, DMX_OK); + demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts); spin_unlock_irqrestore(&demux->lock, flags); } diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index b81e026edab3..ce4332e80a91 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c @@ -761,7 +761,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - struct dmx_ts_feed *feed, enum dmx_success success) + struct dmx_ts_feed *feed) { struct net_device *dev = feed->priv; @@ -870,8 +870,7 @@ static void dvb_net_sec(struct net_device *dev, static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - struct dmx_section_filter *filter, - enum dmx_success success) + struct dmx_section_filter *filter) { struct net_device *dev = filter->priv; diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h index c61a4f03a66f..1069a776bbdb 100644 --- a/drivers/media/dvb-core/dvbdev.h +++ b/drivers/media/dvb-core/dvbdev.h @@ -184,10 +184,6 @@ int dvb_unregister_adapter(struct dvb_adapter *adap); * @pdvbdev: pointer to the place where the new struct dvb_device will be * stored * @template: Template used to create &pdvbdev; - * @device: pointer to struct device that corresponds to the device driver - * @adapter_nums: Array with a list of the numbers for @dvb_register_adapter; - * to select among them. Typically, initialized with: - * DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums) * @priv: private data * @type: type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND, * DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c index 34b9441840da..445a15c2714f 100644 --- a/drivers/media/dvb-frontends/drxd_hard.c +++ b/drivers/media/dvb-frontends/drxd_hard.c @@ -2950,10 +2950,9 @@ struct dvb_frontend *drxd_attach(const struct drxd_config *config, { struct drxd_state *state = NULL; - state = kmalloc(sizeof(struct drxd_state), GFP_KERNEL); + state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) return NULL; - memset(state, 0, sizeof(*state)); state->ops = drxd_ops; state->dev = dev; diff --git a/drivers/media/dvb-frontends/horus3a.h b/drivers/media/dvb-frontends/horus3a.h index b055319d532e..c1e2d1834b78 100644 --- a/drivers/media/dvb-frontends/horus3a.h +++ b/drivers/media/dvb-frontends/horus3a.h @@ -46,8 +46,8 @@ extern struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe, const struct horus3a_config *config, struct i2c_adapter *i2c); #else -static inline struct dvb_frontend *horus3a_attach( - const struct cxd2820r_config *config, +static inline struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe, + const struct horus3a_config *config, struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); diff --git a/drivers/media/dvb-frontends/lnbh25.h b/drivers/media/dvb-frontends/lnbh25.h index 69f30e21f6b3..1f329ef05acc 100644 --- a/drivers/media/dvb-frontends/lnbh25.h +++ b/drivers/media/dvb-frontends/lnbh25.h @@ -43,7 +43,7 @@ struct dvb_frontend *lnbh25_attach( struct lnbh25_config *cfg, struct i2c_adapter *i2c); #else -static inline dvb_frontend *lnbh25_attach( +static inline struct dvb_frontend *lnbh25_attach( struct dvb_frontend *fe, struct lnbh25_config *cfg, struct i2c_adapter *i2c) diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index ff31e7a01ca9..feeeb70d841e 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -18,6 +18,27 @@ static struct dvb_frontend_ops m88ds3103_ops; +/* write single register with mask */ +static int m88ds3103_update_bits(struct m88ds3103_dev *dev, + u8 reg, u8 mask, u8 val) +{ + int ret; + u8 tmp; + + /* no need for read if whole reg is written */ + if (mask != 0xff) { + ret = regmap_bulk_read(dev->regmap, reg, &tmp, 1); + if (ret) + return ret; + + val &= mask; + tmp &= ~mask; + val |= tmp; + } + + return regmap_bulk_write(dev->regmap, reg, &val, 1); +} + /* write reg val table using reg addr auto increment */ static int m88ds3103_wr_reg_val_tab(struct m88ds3103_dev *dev, const struct m88ds3103_reg_val *tab, int tab_len) @@ -394,10 +415,10 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) u8tmp2 = 0x00; /* 0b00 */ break; } - ret = regmap_update_bits(dev->regmap, 0x22, 0xc0, u8tmp1 << 6); + ret = m88ds3103_update_bits(dev, 0x22, 0xc0, u8tmp1 << 6); if (ret) goto err; - ret = regmap_update_bits(dev->regmap, 0x24, 0xc0, u8tmp2 << 6); + ret = m88ds3103_update_bits(dev, 0x24, 0xc0, u8tmp2 << 6); if (ret) goto err; } @@ -455,13 +476,13 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) if (ret) goto err; } - ret = regmap_update_bits(dev->regmap, 0x9d, 0x08, 0x08); + ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08); if (ret) goto err; ret = regmap_write(dev->regmap, 0xf1, 0x01); if (ret) goto err; - ret = regmap_update_bits(dev->regmap, 0x30, 0x80, 0x80); + ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); if (ret) goto err; } @@ -498,7 +519,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) switch (dev->cfg->ts_mode) { case M88DS3103_TS_SERIAL: case M88DS3103_TS_SERIAL_D7: - ret = regmap_update_bits(dev->regmap, 0x29, 0x20, u8tmp1); + ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1); if (ret) goto err; u8tmp1 = 0; @@ -567,11 +588,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) if (ret) goto err; - ret = regmap_update_bits(dev->regmap, 0x4d, 0x02, dev->cfg->spec_inv << 1); + ret = m88ds3103_update_bits(dev, 0x4d, 0x02, dev->cfg->spec_inv << 1); if (ret) goto err; - ret = regmap_update_bits(dev->regmap, 0x30, 0x10, dev->cfg->agc_inv << 4); + ret = m88ds3103_update_bits(dev, 0x30, 0x10, dev->cfg->agc_inv << 4); if (ret) goto err; @@ -625,13 +646,13 @@ static int m88ds3103_init(struct dvb_frontend *fe) dev->warm = false; /* wake up device from sleep */ - ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x01); + ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x01); if (ret) goto err; - ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x00); + ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x00); if (ret) goto err; - ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x00); + ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x00); if (ret) goto err; @@ -749,18 +770,18 @@ static int m88ds3103_sleep(struct dvb_frontend *fe) utmp = 0x29; else utmp = 0x27; - ret = regmap_update_bits(dev->regmap, utmp, 0x01, 0x00); + ret = m88ds3103_update_bits(dev, utmp, 0x01, 0x00); if (ret) goto err; /* sleep */ - ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00); + ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00); if (ret) goto err; - ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01); + ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01); if (ret) goto err; - ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10); + ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10); if (ret) goto err; @@ -992,12 +1013,12 @@ static int m88ds3103_set_tone(struct dvb_frontend *fe, } utmp = tone << 7 | dev->cfg->envelope_mode << 5; - ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp); + ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp); if (ret) goto err; utmp = 1 << 2; - ret = regmap_update_bits(dev->regmap, 0xa1, reg_a1_mask, utmp); + ret = m88ds3103_update_bits(dev, 0xa1, reg_a1_mask, utmp); if (ret) goto err; @@ -1047,7 +1068,7 @@ static int m88ds3103_set_voltage(struct dvb_frontend *fe, voltage_dis ^= dev->cfg->lnb_en_pol; utmp = voltage_dis << 1 | voltage_sel << 0; - ret = regmap_update_bits(dev->regmap, 0xa2, 0x03, utmp); + ret = m88ds3103_update_bits(dev, 0xa2, 0x03, utmp); if (ret) goto err; @@ -1080,7 +1101,7 @@ static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe, } utmp = dev->cfg->envelope_mode << 5; - ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp); + ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp); if (ret) goto err; @@ -1115,12 +1136,12 @@ static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe, } else { dev_dbg(&client->dev, "diseqc tx timeout\n"); - ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40); + ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40); if (ret) goto err; } - ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80); + ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80); if (ret) goto err; @@ -1152,7 +1173,7 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe, } utmp = dev->cfg->envelope_mode << 5; - ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp); + ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp); if (ret) goto err; @@ -1194,12 +1215,12 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe, } else { dev_dbg(&client->dev, "diseqc tx timeout\n"); - ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40); + ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40); if (ret) goto err; } - ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80); + ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80); if (ret) goto err; @@ -1435,13 +1456,13 @@ static int m88ds3103_probe(struct i2c_client *client, goto err_kfree; /* sleep */ - ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00); + ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00); if (ret) goto err_kfree; - ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01); + ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01); if (ret) goto err_kfree; - ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10); + ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10); if (ret) goto err_kfree; diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index d5b994f17612..dcd8d94c1037 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -29,6 +29,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> #include <linux/platform_device.h> @@ -107,7 +108,8 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats); /* intermediate buffers with raw data from the USB device */ struct rtl2832_sdr_frame_buf { - struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ + /* common v4l buffer stuff -- must be first */ + struct vb2_v4l2_buffer vb; struct list_head list; }; @@ -304,13 +306,13 @@ static void rtl2832_sdr_urb_complete(struct urb *urb) } /* fill framebuffer */ - ptr = vb2_plane_vaddr(&fbuf->vb, 0); + ptr = vb2_plane_vaddr(&fbuf->vb.vb2_buf, 0); len = rtl2832_sdr_convert_stream(dev, ptr, urb->transfer_buffer, urb->actual_length); - vb2_set_plane_payload(&fbuf->vb, 0, len); - v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp); - fbuf->vb.v4l2_buf.sequence = dev->sequence++; - vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); + vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len); + v4l2_get_timestamp(&fbuf->vb.timestamp); + fbuf->vb.sequence = dev->sequence++; + vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); } skip: usb_submit_urb(urb, GFP_ATOMIC); @@ -464,7 +466,7 @@ static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_dev *dev) buf = list_entry(dev->queued_bufs.next, struct rtl2832_sdr_frame_buf, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->queued_bufs_lock, flags); } @@ -488,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 struct v4l2_format *fmt, unsigned int *nbuffers, + const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); @@ -518,14 +520,15 @@ static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb) static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vb->vb2_queue); struct rtl2832_sdr_frame_buf *buf = - container_of(vb, struct rtl2832_sdr_frame_buf, vb); + container_of(vbuf, struct rtl2832_sdr_frame_buf, vb); unsigned long flags; /* Check the device has not disconnected between prep and queuing */ if (!dev->udev) { - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); return; } diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 81788c5a44d8..821a8f481507 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -502,6 +502,10 @@ static int si2168_init(struct dvb_frontend *fe) /* firmware is in the new format */ for (remaining = fw->size; remaining > 0; remaining -= 17) { len = fw->data[fw->size - remaining]; + if (len > SI2168_ARGLEN) { + ret = -EINVAL; + break; + } memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); cmd.wlen = len; cmd.rlen = 1; diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c index af5eaf2db2a0..38a20fe181ee 100644 --- a/drivers/media/i2c/ml86v7667.c +++ b/drivers/media/i2c/ml86v7667.c @@ -233,6 +233,15 @@ static int ml86v7667_g_mbus_config(struct v4l2_subdev *sd, return 0; } +static int ml86v7667_g_std(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + struct ml86v7667_priv *priv = to_ml86v7667(sd); + + *std = priv->std; + + return 0; +} + static int ml86v7667_s_std(struct v4l2_subdev *sd, v4l2_std_id std) { struct ml86v7667_priv *priv = to_ml86v7667(sd); @@ -282,6 +291,7 @@ static const struct v4l2_ctrl_ops ml86v7667_ctrl_ops = { }; static struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = { + .g_std = ml86v7667_g_std, .s_std = ml86v7667_s_std, .querystd = ml86v7667_querystd, .g_input_status = ml86v7667_g_input_status, @@ -427,7 +437,6 @@ MODULE_DEVICE_TABLE(i2c, ml86v7667_id); static struct i2c_driver ml86v7667_i2c_driver = { .driver = { .name = DRV_NAME, - .owner = THIS_MODULE, }, .probe = ml86v7667_probe, .remove = ml86v7667_remove, diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index e691bba1945b..1ee6a5527c38 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -1133,7 +1133,7 @@ static int __ov965x_set_frame_interval(struct ov965x *ov965x, if (mbus_fmt->width != iv->size.width || mbus_fmt->height != iv->size.height) continue; - err = abs64((u64)(iv->interval.numerator * 10000) / + err = abs((u64)(iv->interval.numerator * 10000) / iv->interval.denominator - req_int); if (err < min_err) { fiv = iv; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 53c5ea89f0b9..51b26010403c 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -167,7 +167,7 @@ static int s5c73m3_i2c_read(struct i2c_client *client, u16 addr, u16 *data) */ ret = i2c_transfer(client->adapter, msg, 2); if (ret == 2) { - *data = be16_to_cpup((u16 *)rbuf); + *data = be16_to_cpup((__be16 *)rbuf); v4l2_dbg(4, s5c73m3_dbg, client, "%s: addr: 0x%04x, data: 0x%04x\n", __func__, addr, *data); diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c index fa4a5ebda6b2..72ef9f936e6c 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c @@ -31,6 +31,7 @@ static const struct of_device_id s5c73m3_spi_ids[] = { { .compatible = "samsung,s5c73m3" }, { } }; +MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids); enum spi_direction { SPI_DIR_RX, @@ -149,7 +150,6 @@ int s5c73m3_register_spi_driver(struct s5c73m3 *state) spidrv->remove = s5c73m3_spi_remove; spidrv->probe = s5c73m3_spi_probe; spidrv->driver.name = S5C73M3_SPI_DRV_NAME; - spidrv->driver.owner = THIS_MODULE; spidrv->driver.of_match_table = s5c73m3_spi_ids; return spi_register_driver(spidrv); diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 636ebd6fe5dc..fb39dfd55e75 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -3131,6 +3131,7 @@ static const struct of_device_id smiapp_of_table[] = { { .compatible = "nokia,smia" }, { }, }; +MODULE_DEVICE_TABLE(of, smiapp_of_table); static const struct i2c_device_id smiapp_id_table[] = { { SMIAPP_NAME, 0 }, diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 522a865c5c60..3c5fb2509c47 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -10,6 +10,7 @@ #include <linux/videodev2.h> #include <linux/delay.h> #include <linux/module.h> +#include <media/v4l2-async.h> #include <media/v4l2-device.h> #include <media/tvp5150.h> #include <media/v4l2-ctrls.h> @@ -1172,8 +1173,7 @@ static int tvp5150_probe(struct i2c_client *c, sd->ctrl_handler = &core->hdl; if (core->hdl.error) { res = core->hdl.error; - v4l2_ctrl_handler_free(&core->hdl); - return res; + goto err; } v4l2_ctrl_handler_setup(&core->hdl); @@ -1186,9 +1186,17 @@ static int tvp5150_probe(struct i2c_client *c, core->rect.left = 0; core->rect.width = TVP5150_H_MAX; + res = v4l2_async_register_subdev(sd); + if (res < 0) + goto err; + if (debug > 1) tvp5150_log_status(sd); return 0; + +err: + v4l2_ctrl_handler_free(&core->hdl); + return res; } static int tvp5150_remove(struct i2c_client *c) @@ -1200,7 +1208,7 @@ static int tvp5150_remove(struct i2c_client *c) "tvp5150.c: removing tvp5150 adapter on address 0x%x\n", c->addr << 1); - v4l2_device_unregister_subdev(sd); + v4l2_async_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); return 0; } diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 153a46469814..767fe55ba08e 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -235,8 +235,8 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity, media_entity_graph_walk_start(&graph, entity); while ((entity = media_entity_graph_walk_next(&graph))) { - DECLARE_BITMAP(active, entity->num_pads); - DECLARE_BITMAP(has_no_links, entity->num_pads); + DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS); + DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS); unsigned int i; entity->stream_count++; diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 3632958f2158..15a4ebc2844d 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -3625,13 +3625,10 @@ static void bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup, unsigned int state) { - struct timeval ts; - if (NULL == wakeup) return; - v4l2_get_timestamp(&ts); - wakeup->vb.ts = ts; + v4l2_get_timestamp(&wakeup->vb.ts); wakeup->vb.field_count = btv->field_count; wakeup->vb.state = state; wake_up(&wakeup->vb.done); diff --git a/drivers/media/pci/cobalt/Kconfig b/drivers/media/pci/cobalt/Kconfig index 1f88ccc174da..a01f0cc745cc 100644 --- a/drivers/media/pci/cobalt/Kconfig +++ b/drivers/media/pci/cobalt/Kconfig @@ -1,6 +1,6 @@ config VIDEO_COBALT tristate "Cisco Cobalt support" - depends on VIDEO_V4L2 && I2C && MEDIA_CONTROLLER + depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API depends on PCI_MSI && MTD_COMPLEX_MAPPINGS depends on GPIOLIB || COMPILE_TEST depends on SND diff --git a/drivers/media/pci/cobalt/cobalt-cpld.c b/drivers/media/pci/cobalt/cobalt-cpld.c index e83f5c9f7e7d..23c875fc173e 100644 --- a/drivers/media/pci/cobalt/cobalt-cpld.c +++ b/drivers/media/pci/cobalt/cobalt-cpld.c @@ -290,8 +290,8 @@ bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out) 0x01, 0xc7, 0xfc, 0x7f, 0x53, 0x62). */ - cobalt_dbg(1, "%u: %02x %02x %02x %02x %02x %02x\n", f_out, - regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]); + cobalt_dbg(1, "%u: %6ph\n", f_out, regs); + while (retries--) { u8 read_regs[6]; @@ -330,9 +330,7 @@ bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out) if (!memcmp(read_regs, regs, sizeof(read_regs))) break; - cobalt_dbg(1, "retry: %02x %02x %02x %02x %02x %02x\n", - read_regs[0], read_regs[1], read_regs[2], - read_regs[3], read_regs[4], read_regs[5]); + cobalt_dbg(1, "retry: %6ph\n", read_regs); } if (2 - retries) cobalt_info("Needed %d retries\n", 2 - retries); diff --git a/drivers/media/pci/cobalt/cobalt-driver.h b/drivers/media/pci/cobalt/cobalt-driver.h index c206df930669..b2f08e4a68bf 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.h +++ b/drivers/media/pci/cobalt/cobalt-driver.h @@ -35,6 +35,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-device.h> #include <media/v4l2-fh.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-sg.h> #include "m00233_video_measure_memmap_package.h" @@ -206,11 +207,12 @@ struct sg_dma_desc_info { #define COBALT_STREAM_FL_ADV_IRQ 1 struct cobalt_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; -static inline struct cobalt_buffer *to_cobalt_buffer(struct vb2_buffer *vb2) +static inline +struct cobalt_buffer *to_cobalt_buffer(struct vb2_v4l2_buffer *vb2) { return container_of(vb2, struct cobalt_buffer, vb); } diff --git a/drivers/media/pci/cobalt/cobalt-irq.c b/drivers/media/pci/cobalt/cobalt-irq.c index d1f5898d11ba..3de26d0714b5 100644 --- a/drivers/media/pci/cobalt/cobalt-irq.c +++ b/drivers/media/pci/cobalt/cobalt-irq.c @@ -134,11 +134,12 @@ done: skip = true; s->skip_first_frames--; } - v4l2_get_timestamp(&cb->vb.v4l2_buf.timestamp); + v4l2_get_timestamp(&cb->vb.timestamp); /* TODO: the sequence number should be read from the FPGA so we also know about dropped frames. */ - cb->vb.v4l2_buf.sequence = s->sequence++; - vb2_buffer_done(&cb->vb, (skip || s->unstable_frame) ? + cb->vb.sequence = s->sequence++; + vb2_buffer_done(&cb->vb.vb2_buf, + (skip || s->unstable_frame) ? VB2_BUF_STATE_REQUEUEING : VB2_BUF_STATE_DONE); } diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c index 9756fd3e8af5..ff46e424262f 100644 --- a/drivers/media/pci/cobalt/cobalt-v4l2.c +++ b/drivers/media/pci/cobalt/cobalt-v4l2.c @@ -43,11 +43,11 @@ 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 struct v4l2_format *fmt, +static int cobalt_queue_setup(struct vb2_queue *q, const void *parg, 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; @@ -75,7 +75,7 @@ static int cobalt_buf_init(struct vb2_buffer *vb) const size_t bytes = COBALT_MAX_HEIGHT * max_pages_per_line * 0x20; const size_t audio_bytes = ((1920 * 4) / PAGE_SIZE + 1) * 0x20; - struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->v4l2_buf.index]; + struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->index]; struct sg_table *sg_desc = vb2_dma_sg_plane_desc(vb, 0); unsigned size; int ret; @@ -105,17 +105,18 @@ static int cobalt_buf_init(struct vb2_buffer *vb) static void cobalt_buf_cleanup(struct vb2_buffer *vb) { struct cobalt_stream *s = vb->vb2_queue->drv_priv; - struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->v4l2_buf.index]; + struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->index]; descriptor_list_free(desc); } static int cobalt_buf_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cobalt_stream *s = vb->vb2_queue->drv_priv; vb2_set_plane_payload(vb, 0, s->stride * s->height); - vb->v4l2_buf.field = V4L2_FIELD_NONE; + vbuf->field = V4L2_FIELD_NONE; return 0; } @@ -128,7 +129,7 @@ static void chain_all_buffers(struct cobalt_stream *s) list_for_each(p, &s->bufs) { cb = list_entry(p, struct cobalt_buffer, list); - desc[i] = &s->dma_desc_info[cb->vb.v4l2_buf.index]; + desc[i] = &s->dma_desc_info[cb->vb.vb2_buf.index]; if (i > 0) descriptor_list_chain(desc[i-1], desc[i]); i++; @@ -137,10 +138,11 @@ static void chain_all_buffers(struct cobalt_stream *s) static void cobalt_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *q = vb->vb2_queue; struct cobalt_stream *s = q->drv_priv; - struct cobalt_buffer *cb = to_cobalt_buffer(vb); - struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->v4l2_buf.index]; + struct cobalt_buffer *cb = to_cobalt_buffer(vbuf); + struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->index]; unsigned long flags; /* Prepare new buffer */ @@ -284,7 +286,7 @@ static void cobalt_dma_start_streaming(struct cobalt_stream *s) &vo->control); } cb = list_first_entry(&s->bufs, struct cobalt_buffer, list); - omni_sg_dma_start(s, &s->dma_desc_info[cb->vb.v4l2_buf.index]); + omni_sg_dma_start(s, &s->dma_desc_info[cb->vb.vb2_buf.index]); spin_unlock_irqrestore(&s->irqlock, flags); } @@ -381,7 +383,7 @@ static void cobalt_dma_stop_streaming(struct cobalt_stream *s) spin_lock_irqsave(&s->irqlock, flags); list_for_each(p, &s->bufs) { cb = list_entry(p, struct cobalt_buffer, list); - desc = &s->dma_desc_info[cb->vb.v4l2_buf.index]; + desc = &s->dma_desc_info[cb->vb.vb2_buf.index]; /* Stop DMA after this descriptor chain */ descriptor_list_end_of_chain(desc); } @@ -416,7 +418,7 @@ static void cobalt_stop_streaming(struct vb2_queue *q) list_for_each_safe(p, safe, &s->bufs) { cb = list_entry(p, struct cobalt_buffer, list); list_del(&cb->list); - vb2_buffer_done(&cb->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&cb->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&s->irqlock, flags); diff --git a/drivers/media/pci/cx18/cx18-mailbox.c b/drivers/media/pci/cx18/cx18-mailbox.c index eabf00c6351b..1f8aa9a749a1 100644 --- a/drivers/media/pci/cx18/cx18-mailbox.c +++ b/drivers/media/pci/cx18/cx18-mailbox.c @@ -202,7 +202,7 @@ static void cx18_mdl_send_to_videobuf(struct cx18_stream *s, } if (dispatch) { - vb_buf->vb.ts = ktime_to_timeval(ktime_get()); + v4l2_get_timestamp(&vb_buf->vb.ts); list_del(&vb_buf->vb.queue); vb_buf->vb.state = VIDEOBUF_DONE; wake_up(&vb_buf->vb.done); diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index 63c0ee5d0bf5..88a3afb66d10 100644 --- a/drivers/media/pci/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -1138,7 +1138,7 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder) /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *q, const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -1155,17 +1155,19 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx23885_dev *dev = vb->vb2_queue->drv_priv; struct cx23885_buffer *buf = - container_of(vb, struct cx23885_buffer, vb); + container_of(vbuf, struct cx23885_buffer, vb); return cx23885_buf_prepare(buf, &dev->ts1); } static void buffer_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx23885_dev *dev = vb->vb2_queue->drv_priv; - struct cx23885_buffer *buf = container_of(vb, + struct cx23885_buffer *buf = container_of(vbuf, struct cx23885_buffer, vb); cx23885_free_buffer(dev, buf); @@ -1173,8 +1175,9 @@ static void buffer_finish(struct vb2_buffer *vb) static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx23885_dev *dev = vb->vb2_queue->drv_priv; - struct cx23885_buffer *buf = container_of(vb, + struct cx23885_buffer *buf = container_of(vbuf, struct cx23885_buffer, vb); cx23885_buf_queue(&dev->ts1, buf); @@ -1201,7 +1204,7 @@ static int cx23885_start_streaming(struct vb2_queue *q, unsigned int count) struct cx23885_buffer, queue); list_del(&buf->queue); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); } spin_unlock_irqrestore(&dev->slock, flags); return ret; diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index 7aee76af7a85..e8f847226a19 100644 --- a/drivers/media/pci/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c @@ -427,12 +427,13 @@ static void cx23885_wakeup(struct cx23885_tsport *port, buf = list_entry(q->active.next, struct cx23885_buffer, queue); - v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); - buf->vb.v4l2_buf.sequence = q->count++; - dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.v4l2_buf.index, + v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.sequence = q->count++; + dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf, + buf->vb.vb2_buf.index, count, q->count); list_del(&buf->queue); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } int cx23885_sram_channel_setup(struct cx23885_dev *dev, @@ -1453,12 +1454,12 @@ int cx23885_buf_prepare(struct cx23885_buffer *buf, struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; int size = port->ts_packet_size * port->ts_packet_count; - struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0); + struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0); dprintk(1, "%s: %p\n", __func__, buf); - if (vb2_plane_size(&buf->vb, 0) < size) + if (vb2_plane_size(&buf->vb.vb2_buf, 0) < size) return -EINVAL; - vb2_set_plane_payload(&buf->vb, 0, size); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); cx23885_risc_databuffer(dev->pci, &buf->risc, sgt->sgl, @@ -1503,7 +1504,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf) if (list_empty(&cx88q->active)) { list_add_tail(&buf->queue, &cx88q->active); dprintk(1, "[%p/%d] %s - first active\n", - buf, buf->vb.v4l2_buf.index, __func__); + buf, buf->vb.vb2_buf.index, __func__); } else { buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); prev = list_entry(cx88q->active.prev, struct cx23885_buffer, @@ -1511,7 +1512,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf) list_add_tail(&buf->queue, &cx88q->active); prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); dprintk(1, "[%p/%d] %s - append to active\n", - buf, buf->vb.v4l2_buf.index, __func__); + buf, buf->vb.vb2_buf.index, __func__); } spin_unlock_irqrestore(&dev->slock, flags); } @@ -1530,9 +1531,10 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason) buf = list_entry(q->active.next, struct cx23885_buffer, queue); list_del(&buf->queue); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); dprintk(1, "[%p/%d] %s - dma=0x%08lx\n", - buf, buf->vb.v4l2_buf.index, reason, (unsigned long)buf->risc.dma); + buf, buf->vb.vb2_buf.index, reason, + (unsigned long)buf->risc.dma); } spin_unlock_irqrestore(&port->slock, flags); } @@ -1990,9 +1992,9 @@ static int cx23885_initdev(struct pci_dev *pci_dev, (unsigned long long)pci_resource_start(pci_dev, 0)); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev, 0xffffffff)) { + err = pci_set_dma_mask(pci_dev, 0xffffffff); + if (err) { printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); - err = -EIO; goto fail_context; } diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 6e8c24cdb2cd..c4307ad8594c 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 struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *q, const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -110,18 +110,20 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx23885_tsport *port = vb->vb2_queue->drv_priv; struct cx23885_buffer *buf = - container_of(vb, struct cx23885_buffer, vb); + container_of(vbuf, struct cx23885_buffer, vb); return cx23885_buf_prepare(buf, port); } static void buffer_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx23885_tsport *port = vb->vb2_queue->drv_priv; struct cx23885_dev *dev = port->dev; - struct cx23885_buffer *buf = container_of(vb, + struct cx23885_buffer *buf = container_of(vbuf, struct cx23885_buffer, vb); cx23885_free_buffer(dev, buf); @@ -129,8 +131,9 @@ static void buffer_finish(struct vb2_buffer *vb) static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx23885_tsport *port = vb->vb2_queue->drv_priv; - struct cx23885_buffer *buf = container_of(vb, + struct cx23885_buffer *buf = container_of(vbuf, struct cx23885_buffer, vb); cx23885_buf_queue(port, buf); diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c index d362d3838c84..cf3cb1324c55 100644 --- a/drivers/media/pci/cx23885/cx23885-vbi.c +++ b/drivers/media/pci/cx23885/cx23885-vbi.c @@ -121,7 +121,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev, /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *q, const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -138,8 +138,9 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx23885_dev *dev = vb->vb2_queue->drv_priv; - struct cx23885_buffer *buf = container_of(vb, + struct cx23885_buffer *buf = container_of(vbuf, struct cx23885_buffer, vb); struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); unsigned lines = VBI_PAL_LINE_COUNT; @@ -161,7 +162,8 @@ static int buffer_prepare(struct vb2_buffer *vb) static void buffer_finish(struct vb2_buffer *vb) { - struct cx23885_buffer *buf = container_of(vb, + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct cx23885_buffer *buf = container_of(vbuf, struct cx23885_buffer, vb); cx23885_free_buffer(vb->vb2_queue->drv_priv, buf); @@ -190,8 +192,10 @@ static void buffer_finish(struct vb2_buffer *vb) */ static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx23885_dev *dev = vb->vb2_queue->drv_priv; - struct cx23885_buffer *buf = container_of(vb, struct cx23885_buffer, vb); + struct cx23885_buffer *buf = container_of(vbuf, + struct cx23885_buffer, vb); struct cx23885_buffer *prev; struct cx23885_dmaqueue *q = &dev->vbiq; unsigned long flags; @@ -206,7 +210,7 @@ static void buffer_queue(struct vb2_buffer *vb) list_add_tail(&buf->queue, &q->active); spin_unlock_irqrestore(&dev->slock, flags); dprintk(2, "[%p/%d] vbi_queue - first active\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } else { buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); @@ -217,7 +221,7 @@ static void buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&dev->slock, flags); prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); dprintk(2, "[%p/%d] buffer_queue - append to active\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } } @@ -245,7 +249,7 @@ static void cx23885_stop_streaming(struct vb2_queue *q) struct cx23885_buffer, queue); list_del(&buf->queue); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); } diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index ec76470d12a4..71a80e2b842c 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c @@ -104,12 +104,12 @@ void cx23885_video_wakeup(struct cx23885_dev *dev, buf = list_entry(q->active.next, struct cx23885_buffer, queue); - buf->vb.v4l2_buf.sequence = q->count++; - v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); - dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.v4l2_buf.index, - count, q->count); + buf->vb.sequence = q->count++; + v4l2_get_timestamp(&buf->vb.timestamp); + dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, + buf->vb.vb2_buf.index, count, q->count); list_del(&buf->queue); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) @@ -315,7 +315,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev, return 0; } -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *q, const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -329,9 +329,10 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx23885_dev *dev = vb->vb2_queue->drv_priv; struct cx23885_buffer *buf = - container_of(vb, struct cx23885_buffer, vb); + container_of(vbuf, struct cx23885_buffer, vb); u32 line0_offset, line1_offset; struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); int field_tff; @@ -401,7 +402,7 @@ static int buffer_prepare(struct vb2_buffer *vb) BUG(); } dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", - buf, buf->vb.v4l2_buf.index, + buf, buf->vb.vb2_buf.index, dev->width, dev->height, dev->fmt->depth, dev->fmt->name, (unsigned long)buf->risc.dma); return 0; @@ -409,7 +410,8 @@ static int buffer_prepare(struct vb2_buffer *vb) static void buffer_finish(struct vb2_buffer *vb) { - struct cx23885_buffer *buf = container_of(vb, + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct cx23885_buffer *buf = container_of(vbuf, struct cx23885_buffer, vb); cx23885_free_buffer(vb->vb2_queue->drv_priv, buf); @@ -438,8 +440,9 @@ static void buffer_finish(struct vb2_buffer *vb) */ static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx23885_dev *dev = vb->vb2_queue->drv_priv; - struct cx23885_buffer *buf = container_of(vb, + struct cx23885_buffer *buf = container_of(vbuf, struct cx23885_buffer, vb); struct cx23885_buffer *prev; struct cx23885_dmaqueue *q = &dev->vidq; @@ -455,7 +458,7 @@ static void buffer_queue(struct vb2_buffer *vb) if (list_empty(&q->active)) { list_add_tail(&buf->queue, &q->active); dprintk(2, "[%p/%d] buffer_queue - first active\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } else { buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); prev = list_entry(q->active.prev, struct cx23885_buffer, @@ -463,7 +466,7 @@ static void buffer_queue(struct vb2_buffer *vb) list_add_tail(&buf->queue, &q->active); prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); dprintk(2, "[%p/%d] buffer_queue - append to active\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } spin_unlock_irqrestore(&dev->slock, flags); } @@ -492,7 +495,7 @@ static void cx23885_stop_streaming(struct vb2_queue *q) struct cx23885_buffer, queue); list_del(&buf->queue); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); } diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h index 027ead438194..c5ba0833f47a 100644 --- a/drivers/media/pci/cx23885/cx23885.h +++ b/drivers/media/pci/cx23885/cx23885.h @@ -170,7 +170,7 @@ struct cx23885_riscmem { /* buffer for one video frame */ struct cx23885_buffer { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head queue; /* cx23885 specific */ diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index 24f964bcc53a..b602eba2b601 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c @@ -102,7 +102,7 @@ struct cx25821_audio_dev { static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 }; +static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled."); diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index 559f8293c53a..0042803a9de7 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -1319,7 +1319,8 @@ static int cx25821_initdev(struct pci_dev *pci_dev, dev->pci_lat, (unsigned long long)dev->base_io_addr); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev, 0xffffffff)) { + err = pci_set_dma_mask(pci_dev, 0xffffffff); + if (err) { pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); err = -EIO; goto fail_irq; diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index 7bc495e4ece2..26e3e296d615 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -130,10 +130,10 @@ 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.v4l2_buf.timestamp); - buf->vb.v4l2_buf.sequence = dmaq->count++; + v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.sequence = dmaq->count++; list_del(&buf->queue); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } spin_unlock(&dev->slock); handled++; @@ -141,10 +141,11 @@ 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 struct v4l2_format *fmt, +static int cx25821_queue_setup(struct vb2_queue *q, const void *parg, 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; @@ -159,10 +160,11 @@ static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fm static int cx25821_buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx25821_channel *chan = vb->vb2_queue->drv_priv; struct cx25821_dev *dev = chan->dev; struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); + container_of(vbuf, struct cx25821_buffer, vb); struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); u32 line0_offset; int bpl_local = LINE_SIZE_D1; @@ -176,7 +178,7 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb) if (vb2_plane_size(vb, 0) < chan->height * buf->bpl) return -EINVAL; vb2_set_plane_payload(vb, 0, chan->height * buf->bpl); - buf->vb.v4l2_buf.field = chan->field; + buf->vb.field = chan->field; if (chan->pixel_formats == PIXEL_FRMT_411) { bpl_local = buf->bpl; @@ -231,7 +233,7 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb) } dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", - buf, buf->vb.v4l2_buf.index, chan->width, chan->height, + buf, buf->vb.vb2_buf.index, chan->width, chan->height, chan->fmt->depth, chan->fmt->name, (unsigned long)buf->risc.dma); @@ -240,8 +242,9 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb) static void cx25821_buffer_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); + container_of(vbuf, struct cx25821_buffer, vb); struct cx25821_channel *chan = vb->vb2_queue->drv_priv; struct cx25821_dev *dev = chan->dev; @@ -250,8 +253,9 @@ static void cx25821_buffer_finish(struct vb2_buffer *vb) static void cx25821_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); + container_of(vbuf, struct cx25821_buffer, vb); struct cx25821_channel *chan = vb->vb2_queue->drv_priv; struct cx25821_dev *dev = chan->dev; struct cx25821_buffer *prev; @@ -300,7 +304,7 @@ static void cx25821_stop_streaming(struct vb2_queue *q) struct cx25821_buffer, queue); list_del(&buf->queue); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); } diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h index d81a08a2df4f..a513b68be0fa 100644 --- a/drivers/media/pci/cx25821/cx25821.h +++ b/drivers/media/pci/cx25821/cx25821.h @@ -34,6 +34,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-sg.h> #include "cx25821-reg.h" @@ -127,7 +128,7 @@ struct cx25821_riscmem { /* buffer for one video frame */ struct cx25821_buffer { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head queue; /* cx25821 specific */ diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index 7f8dc60028d5..1b5268f9bb24 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c @@ -101,7 +101,7 @@ typedef struct cx88_audio_dev snd_cx88_card_t; static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; +static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); @@ -890,9 +890,9 @@ static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci, return err; } - if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) { + err = pci_set_dma_mask(pci,DMA_BIT_MASK(32)); + if (err) { dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name); - err = -EIO; cx88_core_put(core, pci); return err; } diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c index 24216efa56e7..8b889135be8a 100644 --- a/drivers/media/pci/cx88/cx88-blackbird.c +++ b/drivers/media/pci/cx88/cx88-blackbird.c @@ -637,7 +637,7 @@ static int blackbird_stop_codec(struct cx8802_dev *dev) /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *q, const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -653,16 +653,18 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8802_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); return cx8802_buf_prepare(vb->vb2_queue, dev, buf); } static void buffer_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8802_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); struct cx88_riscmem *risc = &buf->risc; if (risc->cpu) @@ -672,8 +674,9 @@ static void buffer_finish(struct vb2_buffer *vb) static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8802_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); cx8802_buf_queue(dev, buf); } @@ -721,7 +724,7 @@ fail: struct cx88_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); } spin_unlock_irqrestore(&dev->slock, flags); return err; @@ -749,7 +752,7 @@ static void stop_streaming(struct vb2_queue *q) struct cx88_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); } diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c index aab7cf4c9825..9a43c7826b60 100644 --- a/drivers/media/pci/cx88/cx88-core.c +++ b/drivers/media/pci/cx88/cx88-core.c @@ -518,11 +518,11 @@ void cx88_wakeup(struct cx88_core *core, buf = list_entry(q->active.next, struct cx88_buffer, list); - v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); - buf->vb.v4l2_buf.field = core->field; - buf->vb.v4l2_buf.sequence = q->count++; + v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.field = core->field; + buf->vb.sequence = q->count++; list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } void cx88_shutdown(struct cx88_core *core) diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index 9dfa5ee32a8f..f04835073844 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 struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *q, const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -99,16 +99,18 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8802_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); return cx8802_buf_prepare(vb->vb2_queue, dev, buf); } static void buffer_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8802_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); struct cx88_riscmem *risc = &buf->risc; if (risc->cpu) @@ -118,8 +120,9 @@ static void buffer_finish(struct vb2_buffer *vb) static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8802_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); cx8802_buf_queue(dev, buf); } @@ -149,7 +152,7 @@ static void stop_streaming(struct vb2_queue *q) struct cx88_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); } diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c index 34f505744477..f34c229f9b37 100644 --- a/drivers/media/pci/cx88/cx88-mpeg.c +++ b/drivers/media/pci/cx88/cx88-mpeg.c @@ -214,7 +214,7 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, buf = list_entry(q->active.next, struct cx88_buffer, list); dprintk(2,"restart_queue [%p/%d]: restart dma\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); cx8802_start_dma(dev, q, buf); return 0; } @@ -225,13 +225,13 @@ int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev, struct cx88_buffer *buf) { int size = dev->ts_packet_size * dev->ts_packet_count; - struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0); + struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0); struct cx88_riscmem *risc = &buf->risc; int rc; - if (vb2_plane_size(&buf->vb, 0) < size) + if (vb2_plane_size(&buf->vb.vb2_buf, 0) < size) return -EINVAL; - vb2_set_plane_payload(&buf->vb, 0, size); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); rc = cx88_risc_databuffer(dev->pci, risc, sgt->sgl, dev->ts_packet_size, dev->ts_packet_count, 0); @@ -259,7 +259,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) dprintk( 1, "queue is empty - first active\n" ); list_add_tail(&buf->list, &cx88q->active); dprintk(1,"[%p/%d] %s - first active\n", - buf, buf->vb.v4l2_buf.index, __func__); + buf, buf->vb.vb2_buf.index, __func__); } else { buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); @@ -268,7 +268,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) list_add_tail(&buf->list, &cx88q->active); prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); dprintk( 1, "[%p/%d] %s - append to active\n", - buf, buf->vb.v4l2_buf.index, __func__); + buf, buf->vb.vb2_buf.index, __func__); } } @@ -284,7 +284,7 @@ static void do_cancel_buffers(struct cx8802_dev *dev) while (!list_empty(&q->active)) { buf = list_entry(q->active.next, struct cx88_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock,flags); } @@ -393,7 +393,8 @@ static int cx8802_init_common(struct cx8802_dev *dev) if (pci_enable_device(dev->pci)) return -EIO; pci_set_master(dev->pci); - if (!pci_dma_supported(dev->pci,DMA_BIT_MASK(32))) { + err = pci_set_dma_mask(dev->pci,DMA_BIT_MASK(32)); + if (err) { printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name); return -EIO; } diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c index 7510e80eb2ff..007a5eee8e5e 100644 --- a/drivers/media/pci/cx88/cx88-vbi.c +++ b/drivers/media/pci/cx88/cx88-vbi.c @@ -100,14 +100,14 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev, buf = list_entry(q->active.next, struct cx88_buffer, list); dprintk(2,"restart_queue [%p/%d]: restart dma\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); cx8800_start_vbi_dma(dev, q, buf); return 0; } /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *q, const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -125,8 +125,9 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8800_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); unsigned int lines; unsigned int size; @@ -149,8 +150,9 @@ static int buffer_prepare(struct vb2_buffer *vb) static void buffer_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8800_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); struct cx88_riscmem *risc = &buf->risc; if (risc->cpu) @@ -160,8 +162,9 @@ static void buffer_finish(struct vb2_buffer *vb) static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8800_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); struct cx88_buffer *prev; struct cx88_dmaqueue *q = &dev->vbiq; @@ -174,7 +177,7 @@ static void buffer_queue(struct vb2_buffer *vb) list_add_tail(&buf->list, &q->active); cx8800_start_vbi_dma(dev, q, buf); dprintk(2,"[%p/%d] vbi_queue - first active\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } else { buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); @@ -182,7 +185,7 @@ static void buffer_queue(struct vb2_buffer *vb) list_add_tail(&buf->list, &q->active); prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); dprintk(2,"[%p/%d] buffer_queue - append to active\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } } @@ -213,7 +216,7 @@ static void stop_streaming(struct vb2_queue *q) struct cx88_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); } diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index 400e5caefd58..aef9acf351f6 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -420,7 +420,7 @@ static int restart_video_queue(struct cx8800_dev *dev, if (!list_empty(&q->active)) { buf = list_entry(q->active.next, struct cx88_buffer, list); dprintk(2,"restart_queue [%p/%d]: restart dma\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); start_video_dma(dev, q, buf); } return 0; @@ -429,7 +429,7 @@ static int restart_video_queue(struct cx8800_dev *dev, /* ------------------------------------------------------------------ */ -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *q, const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -444,9 +444,10 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8800_dev *dev = vb->vb2_queue->drv_priv; struct cx88_core *core = dev->core; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); buf->bpl = core->width * dev->fmt->depth >> 3; @@ -489,7 +490,7 @@ static int buffer_prepare(struct vb2_buffer *vb) break; } dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", - buf, buf->vb.v4l2_buf.index, + buf, buf->vb.vb2_buf.index, core->width, core->height, dev->fmt->depth, dev->fmt->name, (unsigned long)buf->risc.dma); return 0; @@ -497,8 +498,9 @@ static int buffer_prepare(struct vb2_buffer *vb) static void buffer_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8800_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); struct cx88_riscmem *risc = &buf->risc; if (risc->cpu) @@ -508,8 +510,9 @@ static void buffer_finish(struct vb2_buffer *vb) static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8800_dev *dev = vb->vb2_queue->drv_priv; - struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); + struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); struct cx88_buffer *prev; struct cx88_core *core = dev->core; struct cx88_dmaqueue *q = &dev->vidq; @@ -522,7 +525,7 @@ static void buffer_queue(struct vb2_buffer *vb) if (list_empty(&q->active)) { list_add_tail(&buf->list, &q->active); dprintk(2,"[%p/%d] buffer_queue - first active\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } else { buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); @@ -530,7 +533,7 @@ static void buffer_queue(struct vb2_buffer *vb) list_add_tail(&buf->list, &q->active); prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); dprintk(2, "[%p/%d] buffer_queue - append to active\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } } @@ -560,7 +563,7 @@ static void stop_streaming(struct vb2_queue *q) struct cx88_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); } @@ -1311,9 +1314,9 @@ static int cx8800_initdev(struct pci_dev *pci_dev, dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0)); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev,DMA_BIT_MASK(32))) { + err = pci_set_dma_mask(pci_dev,DMA_BIT_MASK(32)); + if (err) { printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name); - err = -EIO; goto fail_core; } dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev); diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index 785fe2e0d702..2996eb3ea1fc 100644 --- a/drivers/media/pci/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h @@ -321,7 +321,7 @@ struct cx88_riscmem { /* buffer for one video frame */ struct cx88_buffer { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; /* cx88 specific */ diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c index 8df634518927..d84abde5ea29 100644 --- a/drivers/media/pci/dt3155/dt3155.c +++ b/drivers/media/pci/dt3155/dt3155.c @@ -131,11 +131,12 @@ static int wait_i2c_reg(void __iomem *addr) } static int -dt3155_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +dt3155_queue_setup(struct vb2_queue *vq, const void *parg, 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; @@ -160,7 +161,7 @@ static int dt3155_buf_prepare(struct vb2_buffer *vb) static int dt3155_start_streaming(struct vb2_queue *q, unsigned count) { struct dt3155_priv *pd = vb2_get_drv_priv(q); - struct vb2_buffer *vb = pd->curr_buf; + struct vb2_buffer *vb = &pd->curr_buf->vb2_buf; dma_addr_t dma_addr; pd->sequence = 0; @@ -208,7 +209,7 @@ static void dt3155_stop_streaming(struct vb2_queue *q) spin_lock_irq(&pd->lock); if (pd->curr_buf) { - vb2_buffer_done(pd->curr_buf, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&pd->curr_buf->vb2_buf, VB2_BUF_STATE_ERROR); pd->curr_buf = NULL; } @@ -222,6 +223,7 @@ static void dt3155_stop_streaming(struct vb2_queue *q) static void dt3155_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue); /* pd->vidq.streaming = 1 when dt3155_buf_queue() is invoked */ @@ -229,7 +231,7 @@ static void dt3155_buf_queue(struct vb2_buffer *vb) if (pd->curr_buf) list_add_tail(&vb->done_entry, &pd->dmaq); else - pd->curr_buf = vb; + pd->curr_buf = vbuf; spin_unlock_irq(&pd->lock); } @@ -269,14 +271,14 @@ 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->v4l2_buf.timestamp); - ipd->curr_buf->v4l2_buf.sequence = ipd->sequence++; - ipd->curr_buf->v4l2_buf.field = V4L2_FIELD_NONE; - vb2_buffer_done(ipd->curr_buf, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&ipd->curr_buf->timestamp); + 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); ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry); list_del(&ivb->done_entry); - ipd->curr_buf = ivb; + ipd->curr_buf = to_vb2_v4l2_buffer(ivb); dma_addr = vb2_dma_contig_plane_dma_addr(ivb, 0); iowrite32(dma_addr, ipd->regs + EVEN_DMA_START); iowrite32(dma_addr + ipd->width, ipd->regs + ODD_DMA_START); diff --git a/drivers/media/pci/dt3155/dt3155.h b/drivers/media/pci/dt3155/dt3155.h index 4e1f4d598d57..b3531e0bc733 100644 --- a/drivers/media/pci/dt3155/dt3155.h +++ b/drivers/media/pci/dt3155/dt3155.h @@ -22,6 +22,7 @@ #include <linux/interrupt.h> #include <media/v4l2-device.h> #include <media/v4l2-dev.h> +#include <media/videobuf2-v4l2.h> #define DT3155_NAME "dt3155" #define DT3155_VER_MAJ 2 @@ -181,7 +182,7 @@ struct dt3155_priv { struct pci_dev *pdev; struct vb2_queue vidq; struct vb2_alloc_ctx *alloc_ctx; - struct vb2_buffer *curr_buf; + struct vb2_v4l2_buffer *curr_buf; struct mutex mux; struct list_head dmaq; spinlock_t lock; diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c index 41fa21534edf..8a86b61a896d 100644 --- a/drivers/media/pci/ivtv/ivtv-alsa-main.c +++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c @@ -41,6 +41,7 @@ #include "ivtv-alsa-pcm.h" int ivtv_alsa_debug; +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; #define IVTV_DEBUG_ALSA_INFO(fmt, arg...) \ do { \ @@ -54,6 +55,10 @@ MODULE_PARM_DESC(debug, "\t\t\t 1/0x0001: warning\n" "\t\t\t 2/0x0002: info\n"); +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, + "Index value for IVTV ALSA capture interface(s).\n"); + MODULE_AUTHOR("Andy Walls"); MODULE_DESCRIPTION("CX23415/CX23416 ALSA Interface"); MODULE_SUPPORTED_DEVICE("CX23415/CX23416 MPEG2 encoder"); @@ -137,7 +142,7 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev) struct ivtv *itv = to_ivtv(v4l2_dev); struct snd_card *sc = NULL; struct snd_ivtv_card *itvsc; - int ret; + int ret, idx; /* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */ @@ -145,8 +150,10 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev) /* This is a no-op for us. We'll use the itv->instance */ /* (2) Create a card instance */ + /* use first available id if not specified otherwise*/ + idx = index[itv->instance] == -1 ? SNDRV_DEFAULT_IDX1 : index[itv->instance]; ret = snd_card_new(&itv->pdev->dev, - SNDRV_DEFAULT_IDX1, /* use first available id */ + idx, SNDRV_DEFAULT_STR1, /* xid from end of shortname*/ THIS_MODULE, 0, &sc); if (ret) { @@ -196,6 +203,9 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev) goto err_exit_free; } + IVTV_ALSA_INFO("%s: Instance %d registered as ALSA card %d\n", + __func__, itv->instance, sc->number); + return 0; err_exit_free: diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c index 2ad65eb29832..2b8e7b2f2b86 100644 --- a/drivers/media/pci/ivtv/ivtv-yuv.c +++ b/drivers/media/pci/ivtv/ivtv-yuv.c @@ -75,15 +75,15 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height); /* Get user pages for DMA Xfer */ - down_read(¤t->mm->mmap_sem); - y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL); + y_pages = get_user_pages_unlocked(current, current->mm, + y_dma.uaddr, y_dma.page_count, 0, 1, + &dma->map[0]); uv_pages = 0; /* silence gcc. value is set and consumed only if: */ if (y_pages == y_dma.page_count) { - uv_pages = get_user_pages(current, current->mm, - uv_dma.uaddr, uv_dma.page_count, 0, 1, - &dma->map[y_pages], NULL); + uv_pages = get_user_pages_unlocked(current, current->mm, + uv_dma.uaddr, uv_dma.page_count, 0, 1, + &dma->map[y_pages]); } - up_read(¤t->mm->mmap_sem); if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) { int rc = -EFAULT; diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb.h b/drivers/media/pci/netup_unidvb/netup_unidvb.h index fa951102d7fb..a67b28111905 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb.h +++ b/drivers/media/pci/netup_unidvb/netup_unidvb.h @@ -54,7 +54,7 @@ struct netup_dma { u8 num; spinlock_t lock; struct netup_unidvb_dev *ndev; - struct netup_dma_regs *regs; + struct netup_dma_regs __iomem *regs; u32 ring_buffer_size; u8 *addr_virt; dma_addr_t addr_phys; @@ -82,7 +82,7 @@ struct netup_i2c { wait_queue_head_t wq; struct i2c_adapter adap; struct netup_unidvb_dev *dev; - struct netup_i2c_regs *regs; + struct netup_i2c_regs __iomem *regs; struct i2c_msg *msg; enum netup_i2c_state state; u32 xmit_size; diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c b/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c index 751b51b03593..f46ffac66ee9 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c @@ -147,7 +147,7 @@ static int netup_unidvb_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221, { struct netup_ci_state *state = en50221->data; struct netup_unidvb_dev *dev = state->dev; - u8 val = state->membase8_config[addr]; + u8 val = *((u8 __force *)state->membase8_io + addr); dev_dbg(&dev->pci_dev->dev, "%s(): addr=0x%x val=0x%x\n", __func__, addr, val); @@ -162,7 +162,7 @@ static int netup_unidvb_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221, dev_dbg(&dev->pci_dev->dev, "%s(): addr=0x%x data=0x%x\n", __func__, addr, data); - state->membase8_config[addr] = data; + *((u8 __force *)state->membase8_io + addr) = data; return 0; } @@ -171,7 +171,7 @@ static int netup_unidvb_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, { struct netup_ci_state *state = en50221->data; struct netup_unidvb_dev *dev = state->dev; - u8 val = state->membase8_io[addr]; + u8 val = *((u8 __force *)state->membase8_io + addr); dev_dbg(&dev->pci_dev->dev, "%s(): addr=0x%x val=0x%x\n", __func__, addr, val); @@ -186,7 +186,7 @@ static int netup_unidvb_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, dev_dbg(&dev->pci_dev->dev, "%s(): addr=0x%x data=0x%x\n", __func__, addr, data); - state->membase8_io[addr] = data; + *((u8 __force *)state->membase8_io + addr) = data; return 0; } @@ -226,7 +226,7 @@ int netup_unidvb_ci_register(struct netup_unidvb_dev *dev, __func__, result); return result; } - writew(NETUP_UNIDVB_IRQ_CI, (u16 *)(dev->bmmio0 + REG_IMASK_SET)); + writew(NETUP_UNIDVB_IRQ_CI, dev->bmmio0 + REG_IMASK_SET); dev_info(&pci_dev->dev, "%s(): CI adapter %d init done\n", __func__, num); return 0; diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 6d8bf6277647..3fdbd81b5580 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -27,6 +27,7 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/list.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> #include "netup_unidvb.h" @@ -110,7 +111,7 @@ struct netup_dma_regs { } __packed __aligned(1); struct netup_unidvb_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; u32 size; }; @@ -189,12 +190,10 @@ static void netup_unidvb_dma_enable(struct netup_dma *dma, int enable) "%s(): DMA%d enable %d\n", __func__, dma->num, enable); if (enable) { writel(BIT_DMA_RUN, &dma->regs->ctrlstat_set); - writew(irq_mask, - (u16 *)(dma->ndev->bmmio0 + REG_IMASK_SET)); + writew(irq_mask, dma->ndev->bmmio0 + REG_IMASK_SET); } else { writel(BIT_DMA_RUN, &dma->regs->ctrlstat_clear); - writew(irq_mask, - (u16 *)(dma->ndev->bmmio0 + REG_IMASK_CLEAR)); + writew(irq_mask, dma->ndev->bmmio0 + REG_IMASK_CLEAR); } } @@ -278,7 +277,7 @@ static irqreturn_t netup_unidvb_isr(int irq, void *dev_id) } static int netup_unidvb_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], @@ -300,7 +299,8 @@ static int netup_unidvb_queue_setup(struct vb2_queue *vq, static int netup_unidvb_buf_prepare(struct vb2_buffer *vb) { struct netup_dma *dma = vb2_get_drv_priv(vb->vb2_queue); - struct netup_unidvb_buffer *buf = container_of(vb, + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct netup_unidvb_buffer *buf = container_of(vbuf, struct netup_unidvb_buffer, vb); dev_dbg(&dma->ndev->pci_dev->dev, "%s(): buf 0x%p\n", __func__, buf); @@ -312,7 +312,8 @@ static void netup_unidvb_buf_queue(struct vb2_buffer *vb) { unsigned long flags; struct netup_dma *dma = vb2_get_drv_priv(vb->vb2_queue); - struct netup_unidvb_buffer *buf = container_of(vb, + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct netup_unidvb_buffer *buf = container_of(vbuf, struct netup_unidvb_buffer, vb); dev_dbg(&dma->ndev->pci_dev->dev, "%s(): %p\n", __func__, buf); @@ -509,7 +510,7 @@ static int netup_unidvb_ring_copy(struct netup_dma *dma, { u32 copy_bytes, ring_bytes; u32 buff_bytes = NETUP_DMA_PACKETS_COUNT * 188 - buf->size; - u8 *p = vb2_plane_vaddr(&buf->vb, 0); + u8 *p = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); struct netup_unidvb_dev *ndev = dma->ndev; if (p == NULL) { @@ -522,7 +523,7 @@ static int netup_unidvb_ring_copy(struct netup_dma *dma, ring_bytes = dma->ring_buffer_size - dma->data_offset; copy_bytes = (ring_bytes > buff_bytes) ? buff_bytes : ring_bytes; - memcpy_fromio(p, dma->addr_virt + dma->data_offset, copy_bytes); + memcpy_fromio(p, (u8 __iomem *)(dma->addr_virt + dma->data_offset), copy_bytes); p += copy_bytes; buf->size += copy_bytes; buff_bytes -= copy_bytes; @@ -535,7 +536,7 @@ static int netup_unidvb_ring_copy(struct netup_dma *dma, ring_bytes = dma->data_size; copy_bytes = (ring_bytes > buff_bytes) ? buff_bytes : ring_bytes; - memcpy_fromio(p, dma->addr_virt + dma->data_offset, copy_bytes); + memcpy_fromio(p, (u8 __iomem *)(dma->addr_virt + dma->data_offset), copy_bytes); buf->size += copy_bytes; dma->data_size -= copy_bytes; dma->data_offset += copy_bytes; @@ -579,9 +580,9 @@ 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.v4l2_buf.timestamp); - vb2_set_plane_payload(&buf->vb, 0, buf->size); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&buf->vb.timestamp); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->size); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } } work_done: @@ -599,7 +600,7 @@ static void netup_unidvb_queue_cleanup(struct netup_dma *dma) buf = list_first_entry(&dma->free_buffers, struct netup_unidvb_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dma->lock, flags); } @@ -641,10 +642,10 @@ static int netup_unidvb_dma_init(struct netup_unidvb_dev *ndev, int num) __func__, num, dma->addr_virt, (unsigned long long)dma->addr_phys, dma->ring_buffer_size); - memset_io(dma->addr_virt, 0, dma->ring_buffer_size); + memset_io((u8 __iomem *)dma->addr_virt, 0, dma->ring_buffer_size); dma->addr_last = dma->addr_phys; dma->high_addr = (u32)(dma->addr_phys & 0xC0000000); - dma->regs = (struct netup_dma_regs *)(num == 0 ? + dma->regs = (struct netup_dma_regs __iomem *)(num == 0 ? ndev->bmmio0 + NETUP_DMA0_ADDR : ndev->bmmio0 + NETUP_DMA1_ADDR); writel((NETUP_DMA_BLOCKS_COUNT << 24) | @@ -809,7 +810,7 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev, "%s(): board vendor 0x%x, revision 0x%x\n", __func__, board_vendor, board_revision); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev, 0xffffffff)) { + if (pci_set_dma_mask(pci_dev, 0xffffffff) < 0) { dev_err(&pci_dev->dev, "%s(): 32bit PCI DMA is not supported\n", __func__); goto pci_detect_err; diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c b/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c index eaaa2d0a5fba..c09c52bc6eab 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c @@ -320,7 +320,7 @@ static int netup_i2c_init(struct netup_unidvb_dev *ndev, int bus_num) i2c = &ndev->i2c[bus_num]; spin_lock_init(&i2c->lock); init_waitqueue_head(&i2c->wq); - i2c->regs = (struct netup_i2c_regs *)(ndev->bmmio0 + + i2c->regs = (struct netup_i2c_regs __iomem *)(ndev->bmmio0 + (bus_num == 0 ? NETUP_I2C_BUS0_ADDR : NETUP_I2C_BUS1_ADDR)); netup_i2c_reset(i2c); i2c->adap = netup_i2c_adapter; diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c index f55b3276f28d..f33c0de3e849 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c @@ -45,7 +45,7 @@ struct netup_spi_regs { struct netup_spi { struct device *dev; struct spi_master *master; - struct netup_spi_regs *regs; + struct netup_spi_regs __iomem *regs; u8 __iomem *mmio; spinlock_t lock; wait_queue_head_t waitq; @@ -80,11 +80,9 @@ irqreturn_t netup_spi_interrupt(struct netup_spi *spi) u16 reg; unsigned long flags; - if (!spi) { - dev_dbg(&spi->master->dev, - "%s(): SPI not initialized\n", __func__); + if (!spi) return IRQ_NONE; - } + spin_lock_irqsave(&spi->lock, flags); reg = readw(&spi->regs->control_stat); if (!(reg & NETUP_SPI_CTRL_IRQ)) { @@ -202,7 +200,7 @@ int netup_spi_init(struct netup_unidvb_dev *ndev) spin_lock_init(&nspi->lock); init_waitqueue_head(&nspi->waitq); nspi->master = master; - nspi->regs = (struct netup_spi_regs *)(ndev->bmmio0 + 0x4000); + nspi->regs = (struct netup_spi_regs __iomem *)(ndev->bmmio0 + 0x4000); writew(2, &nspi->regs->clock_divider); writew(NETUP_UNIDVB_IRQ_SPI, ndev->bmmio0 + REG_IMASK_SET); ndev->spi = nspi; @@ -234,11 +232,9 @@ void netup_spi_release(struct netup_unidvb_dev *ndev) unsigned long flags; struct netup_spi *spi = ndev->spi; - if (!spi) { - dev_dbg(&spi->master->dev, - "%s(): SPI not initialized\n", __func__); + if (!spi) return; - } + spin_lock_irqsave(&spi->lock, flags); reg = readw(&spi->regs->control_stat); writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat); diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index c7405766609c..29d2094c42a0 100644 --- a/drivers/media/pci/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c @@ -5884,6 +5884,42 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM] = { + .name = "Leadtek Winfast TV2100 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_TNF_5335MF, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x0d, + .inputs = {{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE1, + .gpio = 0x00, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + .gpio = 0x08, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + .gpio = 0x08, + } }, + .radio = { + .name = name_radio, + .amux = LINE1, + .gpio = 0x04, + }, + .mute = { + .name = name_mute, + .amux = LINE1, + .gpio = 0x08, + }, + }, }; @@ -7149,6 +7185,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0xa10a, .driver_data = SAA7134_BOARD_AVERMEDIA_505, }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x107d, + .subdevice = 0x6f3a, + .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM, + }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -7545,6 +7587,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: + case SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index 72d7f992375e..f720cea80e28 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -216,13 +216,14 @@ int saa7134_buffer_count(unsigned int size, unsigned int count) int saa7134_buffer_startpage(struct saa7134_buf *buf) { - return saa7134_buffer_pages(vb2_plane_size(&buf->vb2, 0)) * buf->vb2.v4l2_buf.index; + return saa7134_buffer_pages(vb2_plane_size(&buf->vb2.vb2_buf, 0)) + * buf->vb2.vb2_buf.index; } unsigned long saa7134_buffer_base(struct saa7134_buf *buf) { unsigned long base; - struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0); + struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2.vb2_buf, 0); base = saa7134_buffer_startpage(buf) * 4096; base += dma->sgl[0].offset; @@ -308,9 +309,9 @@ 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.v4l2_buf.timestamp); - q->curr->vb2.v4l2_buf.sequence = q->seq_nr++; - vb2_buffer_done(&q->curr->vb2, state); + v4l2_get_timestamp(&q->curr->vb2.timestamp); + q->curr->vb2.sequence = q->seq_nr++; + vb2_buffer_done(&q->curr->vb2.vb2_buf, state); q->curr = NULL; } @@ -375,7 +376,8 @@ void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q) if (!list_empty(&q->queue)) { list_for_each_safe(pos, n, &q->queue) { tmp = list_entry(pos, struct saa7134_buf, entry); - vb2_buffer_done(&tmp->vb2, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&tmp->vb2.vb2_buf, + VB2_BUF_STATE_ERROR); list_del(pos); tmp = NULL; } @@ -949,9 +951,9 @@ static int saa7134_initdev(struct pci_dev *pci_dev, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0)); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev, DMA_BIT_MASK(32))) { + err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32)); + if (err) { pr_warn("%s: Oops: no 32bit PCI DMA ???\n", dev->name); - err = -EIO; goto fail1; } diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c index 11a172000291..69d32d3fa32c 100644 --- a/drivers/media/pci/saa7134/saa7134-input.c +++ b/drivers/media/pci/saa7134/saa7134-input.c @@ -835,6 +835,13 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keycode = 0xffff; raw_decode = true; break; + case SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM: + ir_codes = RC_MAP_LEADTEK_Y04G0051; + mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ + mask_keyup = 0x0040000; + mask_keycode = 0xffff; + raw_decode = true; + break; } if (NULL == ir_codes) { pr_err("Oops: IR config error [card=%d]\n", dev->board); diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c index 4b202fa5fbc4..7fb5ee7e20ac 100644 --- a/drivers/media/pci/saa7134/saa7134-ts.c +++ b/drivers/media/pci/saa7134/saa7134-ts.c @@ -79,8 +79,9 @@ static int buffer_activate(struct saa7134_dev *dev, int saa7134_ts_buffer_init(struct vb2_buffer *vb2) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; - struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); + struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2); dmaq->curr = NULL; buf->activate = buffer_activate; @@ -91,9 +92,10 @@ EXPORT_SYMBOL_GPL(saa7134_ts_buffer_init); int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; struct saa7134_dev *dev = dmaq->dev; - struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); + struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2); struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0); unsigned int lines, llength, size; @@ -107,14 +109,14 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2) return -EINVAL; vb2_set_plane_payload(vb2, 0, size); - vb2->v4l2_buf.field = dev->field; + vbuf->field = dev->field; return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents, saa7134_buffer_startpage(buf)); } EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare); -int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, +int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -148,10 +150,12 @@ int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count) list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) { list_del(&buf->entry); - vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb2.vb2_buf, + VB2_BUF_STATE_QUEUED); } if (dmaq->curr) { - vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&dmaq->curr->vb2.vb2_buf, + VB2_BUF_STATE_QUEUED); dmaq->curr = NULL; } return -EBUSY; diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c index 4d36586ad752..6271b0eb0265 100644 --- a/drivers/media/pci/saa7134/saa7134-vbi.c +++ b/drivers/media/pci/saa7134/saa7134-vbi.c @@ -83,7 +83,7 @@ static int buffer_activate(struct saa7134_dev *dev, struct saa7134_buf *buf, struct saa7134_buf *next) { - struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv; + struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.vb2_queue->drv_priv; unsigned long control, base; vbi_dbg("buffer_activate [%p]\n", buf); @@ -119,8 +119,9 @@ static int buffer_prepare(struct vb2_buffer *vb2) { struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; struct saa7134_dev *dev = dmaq->dev; - struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); - struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); + struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2); + struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0); unsigned int size; if (dma->sgl->offset) { @@ -137,7 +138,7 @@ static int buffer_prepare(struct vb2_buffer *vb2) saa7134_buffer_startpage(buf)); } -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *q, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -161,7 +162,8 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, static int buffer_init(struct vb2_buffer *vb2) { struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; - struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); + struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2); dmaq->curr = NULL; buf->activate = buffer_activate; diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 035039cfae6d..518086c7aed5 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -791,7 +791,7 @@ static int buffer_activate(struct saa7134_dev *dev, struct saa7134_buf *buf, struct saa7134_buf *next) { - struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv; + struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.vb2_queue->drv_priv; unsigned long base,control,bpl; unsigned long bpl_uv,lines_uv,base2,base3,tmp; /* planar */ @@ -872,7 +872,8 @@ static int buffer_activate(struct saa7134_dev *dev, static int buffer_init(struct vb2_buffer *vb2) { struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; - struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); + struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2); dmaq->curr = NULL; buf->activate = buffer_activate; @@ -883,8 +884,9 @@ static int buffer_prepare(struct vb2_buffer *vb2) { struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; struct saa7134_dev *dev = dmaq->dev; - struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); - struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); + struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2); + struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0); unsigned int size; if (dma->sgl->offset) { @@ -896,13 +898,13 @@ static int buffer_prepare(struct vb2_buffer *vb2) return -EINVAL; vb2_set_plane_payload(vb2, 0, size); - vb2->v4l2_buf.field = dev->field; + vbuf->field = dev->field; return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents, saa7134_buffer_startpage(buf)); } -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *q, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -932,7 +934,8 @@ void saa7134_vb2_buffer_queue(struct vb2_buffer *vb) { struct saa7134_dmaqueue *dmaq = vb->vb2_queue->drv_priv; struct saa7134_dev *dev = dmaq->dev; - struct saa7134_buf *buf = container_of(vb, struct saa7134_buf, vb2); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2); saa7134_buffer_queue(dev, dmaq, buf); } @@ -953,10 +956,12 @@ int saa7134_vb2_start_streaming(struct vb2_queue *vq, unsigned int count) list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) { list_del(&buf->entry); - vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb2.vb2_buf, + VB2_BUF_STATE_QUEUED); } if (dmaq->curr) { - vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&dmaq->curr->vb2.vb2_buf, + VB2_BUF_STATE_QUEUED); dmaq->curr = NULL; } return -EBUSY; diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 6b5f6f45d285..6b6d234f5cab 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -342,6 +342,7 @@ struct saa7134_card_ir { #define SAA7134_BOARD_AVERMEDIA_A706 192 #define SAA7134_BOARD_WIS_VOYAGER 193 #define SAA7134_BOARD_AVERMEDIA_505 194 +#define SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM 195 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 @@ -459,7 +460,7 @@ struct saa7134_thread { /* buffer for one video/vbi/ts frame */ struct saa7134_buf { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb2; + struct vb2_v4l2_buffer vb2; /* saa7134 specific */ unsigned int top_seen; @@ -819,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 struct v4l2_format *fmt, +int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg, 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/saa7164/Kconfig b/drivers/media/pci/saa7164/Kconfig index a53db7d1c96e..9098ef5feca4 100644 --- a/drivers/media/pci/saa7164/Kconfig +++ b/drivers/media/pci/saa7164/Kconfig @@ -5,7 +5,6 @@ config VIDEO_SAA7164 select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM - select VIDEOBUF_DVB select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c index 3206a826b80d..8bbd092fbe1d 100644 --- a/drivers/media/pci/saa7164/saa7164-core.c +++ b/drivers/media/pci/saa7164/saa7164-core.c @@ -1264,9 +1264,9 @@ static int saa7164_initdev(struct pci_dev *pci_dev, pci_set_master(pci_dev); /* TODO */ - if (!pci_dma_supported(pci_dev, 0xffffffff)) { + err = pci_set_dma_mask(pci_dev, 0xffffffff); + if (err) { printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); - err = -EIO; goto fail_irq; } diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index 4434e0f28c26..1b184c39ba97 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -25,6 +25,18 @@ #define ENCODER_MIN_BITRATE 1000000 #define ENCODER_DEF_BITRATE 5000000 +/* + * This is a dummy non-zero value for the sizeimage field of v4l2_pix_format. + * It is not actually used for anything since this driver does not support + * stream I/O, only read(), and because this driver produces an MPEG stream + * and not discrete frames. But the V4L2 spec doesn't allow for this value + * to be 0, so set it to 0x10000 instead. + * + * If we ever change this driver to support stream I/O, then this field + * will be the size of the streaming buffers. + */ +#define SAA7164_SIZEIMAGE (0x10000) + static struct saa7164_tvnorm saa7164_tvnorms[] = { { .name = "NTSC-M", @@ -35,24 +47,6 @@ static struct saa7164_tvnorm saa7164_tvnorms[] = { } }; -static const u32 saa7164_v4l2_ctrls[] = { - V4L2_CID_BRIGHTNESS, - V4L2_CID_CONTRAST, - V4L2_CID_SATURATION, - V4L2_CID_HUE, - V4L2_CID_AUDIO_VOLUME, - V4L2_CID_SHARPNESS, - V4L2_CID_MPEG_STREAM_TYPE, - V4L2_CID_MPEG_VIDEO_ASPECT, - V4L2_CID_MPEG_VIDEO_B_FRAMES, - V4L2_CID_MPEG_VIDEO_GOP_SIZE, - V4L2_CID_MPEG_AUDIO_MUTE, - V4L2_CID_MPEG_VIDEO_BITRATE_MODE, - V4L2_CID_MPEG_VIDEO_BITRATE, - V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, - 0 -}; - /* Take the encoder configuration form the port struct and * flush it to the hardware. */ @@ -211,10 +205,8 @@ static int saa7164_encoder_initialize(struct saa7164_port *port) } /* -- V4L2 --------------------------------------------------------- */ -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) +int saa7164_s_std(struct saa7164_port *port, v4l2_std_id id) { - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; unsigned int i; @@ -240,22 +232,33 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return 0; } -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) { struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; + return saa7164_s_std(fh->port, id); +} + +int saa7164_g_std(struct saa7164_port *port, v4l2_std_id *id) +{ *id = port->std; return 0; } -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) { - int n; + struct saa7164_encoder_fh *fh = file->private_data; + + return saa7164_g_std(fh->port, id); +} - char *inputs[] = { "tuner", "composite", "svideo", "aux", - "composite 2", "svideo 2", "aux 2" }; +int saa7164_enum_input(struct file *file, void *priv, struct v4l2_input *i) +{ + static const char * const inputs[] = { + "tuner", "composite", "svideo", "aux", + "composite 2", "svideo 2", "aux 2" + }; + int n; if (i->index >= 7) return -EINVAL; @@ -273,10 +276,8 @@ static int vidioc_enum_input(struct file *file, void *priv, return 0; } -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +int saa7164_g_input(struct saa7164_port *port, unsigned int *i) { - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; if (saa7164_api_get_videomux(port) != SAA_OK) @@ -289,10 +290,15 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) return 0; } -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; + + return saa7164_g_input(fh->port, i); +} + +int saa7164_s_input(struct saa7164_port *port, unsigned int i) +{ struct saa7164_dev *dev = port->dev; dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, i); @@ -308,8 +314,14 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) return 0; } -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) +static int vidioc_s_input(struct file *file, void *priv, unsigned int i) +{ + struct saa7164_encoder_fh *fh = file->private_data; + + return saa7164_s_input(fh->port, i); +} + +int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { struct saa7164_encoder_fh *fh = file->private_data; struct saa7164_port *port = fh->port; @@ -319,38 +331,45 @@ static int vidioc_g_tuner(struct file *file, void *priv, return -EINVAL; strcpy(t->name, "tuner"); - t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO; + t->rangelow = SAA7164_TV_MIN_FREQ; + t->rangehigh = SAA7164_TV_MAX_FREQ; dprintk(DBGLVL_ENC, "VIDIOC_G_TUNER: tuner type %d\n", t->type); return 0; } -static int vidioc_s_tuner(struct file *file, void *priv, - const struct v4l2_tuner *t) +int saa7164_s_tuner(struct file *file, void *priv, + const struct v4l2_tuner *t) { + if (0 != t->index) + return -EINVAL; + /* Update the A/V core */ return 0; } -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) +int saa7164_g_frequency(struct saa7164_port *port, struct v4l2_frequency *f) { - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; + if (f->tuner) + return -EINVAL; - f->type = V4L2_TUNER_ANALOG_TV; f->frequency = port->freq; - return 0; } -static int vidioc_s_frequency(struct file *file, void *priv, - const struct v4l2_frequency *f) +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) { struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; + + return saa7164_g_frequency(fh->port, f); +} + +int saa7164_s_frequency(struct saa7164_port *port, + const struct v4l2_frequency *f) +{ struct saa7164_dev *dev = port->dev; struct saa7164_port *tsport; struct dvb_frontend *fe; @@ -370,16 +389,13 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (f->tuner != 0) return -EINVAL; - if (f->type != V4L2_TUNER_ANALOG_TV) - return -EINVAL; - - port->freq = f->frequency; + port->freq = clamp(f->frequency, + SAA7164_TV_MIN_FREQ, SAA7164_TV_MAX_FREQ); /* Update the hardware */ if (port->nr == SAA7164_PORT_ENC1) tsport = &dev->ports[SAA7164_PORT_TS1]; - else - if (port->nr == SAA7164_PORT_ENC2) + else if (port->nr == SAA7164_PORT_ENC2) tsport = &dev->ports[SAA7164_PORT_TS2]; else BUG(); @@ -396,253 +412,54 @@ static int vidioc_s_frequency(struct file *file, void *priv, return 0; } -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) +static int vidioc_s_frequency(struct file *file, void *priv, + const struct v4l2_frequency *f) { struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__, - ctl->id, ctl->value); - - switch (ctl->id) { - case V4L2_CID_BRIGHTNESS: - ctl->value = port->ctl_brightness; - break; - case V4L2_CID_CONTRAST: - ctl->value = port->ctl_contrast; - break; - case V4L2_CID_SATURATION: - ctl->value = port->ctl_saturation; - break; - case V4L2_CID_HUE: - ctl->value = port->ctl_hue; - break; - case V4L2_CID_SHARPNESS: - ctl->value = port->ctl_sharpness; - break; - case V4L2_CID_AUDIO_VOLUME: - ctl->value = port->ctl_volume; - break; - default: - return -EINVAL; - } - return 0; + return saa7164_s_frequency(fh->port, f); } -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) +static int saa7164_s_ctrl(struct v4l2_ctrl *ctrl) { - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; + struct saa7164_port *port = + container_of(ctrl->handler, struct saa7164_port, ctrl_handler); + struct saa7164_encoder_params *params = &port->encoder_params; int ret = 0; - dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__, - ctl->id, ctl->value); - - switch (ctl->id) { + switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_brightness = ctl->value; - saa7164_api_set_usercontrol(port, - PU_BRIGHTNESS_CONTROL); - } else - ret = -EINVAL; + port->ctl_brightness = ctrl->val; + saa7164_api_set_usercontrol(port, PU_BRIGHTNESS_CONTROL); break; case V4L2_CID_CONTRAST: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_contrast = ctl->value; - saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL); - } else - ret = -EINVAL; + port->ctl_contrast = ctrl->val; + saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL); break; case V4L2_CID_SATURATION: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_saturation = ctl->value; - saa7164_api_set_usercontrol(port, - PU_SATURATION_CONTROL); - } else - ret = -EINVAL; + port->ctl_saturation = ctrl->val; + saa7164_api_set_usercontrol(port, PU_SATURATION_CONTROL); break; case V4L2_CID_HUE: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_hue = ctl->value; - saa7164_api_set_usercontrol(port, PU_HUE_CONTROL); - } else - ret = -EINVAL; + port->ctl_hue = ctrl->val; + saa7164_api_set_usercontrol(port, PU_HUE_CONTROL); break; case V4L2_CID_SHARPNESS: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_sharpness = ctl->value; - saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL); - } else - ret = -EINVAL; + port->ctl_sharpness = ctrl->val; + saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL); break; case V4L2_CID_AUDIO_VOLUME: - if ((ctl->value >= -83) && (ctl->value <= 24)) { - port->ctl_volume = ctl->value; - saa7164_api_set_audio_volume(port, port->ctl_volume); - } else - ret = -EINVAL; - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int saa7164_get_ctrl(struct saa7164_port *port, - struct v4l2_ext_control *ctrl) -{ - struct saa7164_encoder_params *params = &port->encoder_params; - - switch (ctrl->id) { - case V4L2_CID_MPEG_VIDEO_BITRATE: - ctrl->value = params->bitrate; - break; - case V4L2_CID_MPEG_STREAM_TYPE: - ctrl->value = params->stream_type; - break; - case V4L2_CID_MPEG_AUDIO_MUTE: - ctrl->value = params->ctl_mute; - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - ctrl->value = params->ctl_aspect; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - ctrl->value = params->bitrate_mode; - break; - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - ctrl->value = params->refdist; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - ctrl->value = params->bitrate_peak; - break; - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - ctrl->value = params->gop_size; - break; - default: - return -EINVAL; - } - return 0; -} - -static int vidioc_g_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = saa7164_get_ctrl(port, ctrl); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - - } - - return -EINVAL; -} - -static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3) -{ - int ret = -EINVAL; - - switch (ctrl->id) { - case V4L2_CID_MPEG_VIDEO_BITRATE: - if ((ctrl->value >= ENCODER_MIN_BITRATE) && - (ctrl->value <= ENCODER_MAX_BITRATE)) - ret = 0; + port->ctl_volume = ctrl->val; + saa7164_api_set_audio_volume(port, port->ctl_volume); break; - case V4L2_CID_MPEG_STREAM_TYPE: - if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) || - (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)) - ret = 0; - break; - case V4L2_CID_MPEG_AUDIO_MUTE: - if ((ctrl->value >= 0) && - (ctrl->value <= 1)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) && - (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - if ((ctrl->value >= 0) && - (ctrl->value <= 255)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - if ((ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) || - (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - if ((ctrl->value >= 1) && - (ctrl->value <= 3)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - if ((ctrl->value >= ENCODER_MIN_BITRATE) && - (ctrl->value <= ENCODER_MAX_BITRATE)) - ret = 0; - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int vidioc_try_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = saa7164_try_ctrl(ctrl, 0); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - } - - return -EINVAL; -} - -static int saa7164_set_ctrl(struct saa7164_port *port, - struct v4l2_ext_control *ctrl) -{ - struct saa7164_encoder_params *params = &port->encoder_params; - int ret = 0; - - switch (ctrl->id) { case V4L2_CID_MPEG_VIDEO_BITRATE: - params->bitrate = ctrl->value; + params->bitrate = ctrl->val; break; case V4L2_CID_MPEG_STREAM_TYPE: - params->stream_type = ctrl->value; + params->stream_type = ctrl->val; break; case V4L2_CID_MPEG_AUDIO_MUTE: - params->ctl_mute = ctrl->value; + params->ctl_mute = ctrl->val; ret = saa7164_api_audio_mute(port, params->ctl_mute); if (ret != SAA_OK) { printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, @@ -651,7 +468,7 @@ static int saa7164_set_ctrl(struct saa7164_port *port, } break; case V4L2_CID_MPEG_VIDEO_ASPECT: - params->ctl_aspect = ctrl->value; + params->ctl_aspect = ctrl->val; ret = saa7164_api_set_aspect_ratio(port); if (ret != SAA_OK) { printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, @@ -660,55 +477,24 @@ static int saa7164_set_ctrl(struct saa7164_port *port, } break; case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - params->bitrate_mode = ctrl->value; + params->bitrate_mode = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_B_FRAMES: - params->refdist = ctrl->value; + params->refdist = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - params->bitrate_peak = ctrl->value; + params->bitrate_peak = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - params->gop_size = ctrl->value; + params->gop_size = ctrl->val; break; default: - return -EINVAL; + ret = -EINVAL; } - /* TODO: Update the hardware */ - return ret; } -static int vidioc_s_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = saa7164_try_ctrl(ctrl, 0); - if (err) { - ctrls->error_idx = i; - break; - } - err = saa7164_set_ctrl(port, ctrl); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - - } - - return -EINVAL; -} - static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { @@ -745,145 +531,22 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, +static int vidioc_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7164_encoder_fh *fh = file->private_data; struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - port->ts_packet_size * port->ts_packet_count; - f->fmt.pix.colorspace = 0; + f->fmt.pix.sizeimage = SAA7164_SIZEIMAGE; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; f->fmt.pix.width = port->width; f->fmt.pix.height = port->height; - - dprintk(DBGLVL_ENC, "VIDIOC_G_FMT: w: %d, h: %d\n", - port->width, port->height); - - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - port->ts_packet_size * port->ts_packet_count; - f->fmt.pix.colorspace = 0; - dprintk(DBGLVL_ENC, "VIDIOC_TRY_FMT: w: %d, h: %d\n", - port->width, port->height); return 0; } -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - port->ts_packet_size * port->ts_packet_count; - f->fmt.pix.colorspace = 0; - - dprintk(DBGLVL_ENC, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", - f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); - - return 0; -} - -static int fill_queryctrl(struct saa7164_encoder_params *params, - struct v4l2_queryctrl *c) -{ - switch (c->id) { - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127); - case V4L2_CID_CONTRAST: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66); - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128); - case V4L2_CID_SHARPNESS: - return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8); - case V4L2_CID_MPEG_AUDIO_MUTE: - return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0); - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(c, -83, 24, 1, 20); - case V4L2_CID_MPEG_VIDEO_BITRATE: - return v4l2_ctrl_query_fill(c, - ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE, - 100000, ENCODER_DEF_BITRATE); - case V4L2_CID_MPEG_STREAM_TYPE: - return v4l2_ctrl_query_fill(c, - V4L2_MPEG_STREAM_TYPE_MPEG2_PS, - V4L2_MPEG_STREAM_TYPE_MPEG2_TS, - 1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS); - case V4L2_CID_MPEG_VIDEO_ASPECT: - return v4l2_ctrl_query_fill(c, - V4L2_MPEG_VIDEO_ASPECT_1x1, - V4L2_MPEG_VIDEO_ASPECT_221x100, - 1, V4L2_MPEG_VIDEO_ASPECT_4x3); - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - return v4l2_ctrl_query_fill(c, 1, 255, 1, 15); - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - return v4l2_ctrl_query_fill(c, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, - 1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - return v4l2_ctrl_query_fill(c, - 1, 3, 1, 1); - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - return v4l2_ctrl_query_fill(c, - ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE, - 100000, ENCODER_DEF_BITRATE); - default: - return -EINVAL; - } -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *c) -{ - struct saa7164_encoder_fh *fh = priv; - struct saa7164_port *port = fh->port; - int i, next; - u32 id = c->id; - - memset(c, 0, sizeof(*c)); - - next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL); - c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL; - - for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) { - if (next) { - if (c->id < saa7164_v4l2_ctrls[i]) - c->id = saa7164_v4l2_ctrls[i]; - else - continue; - } - - if (c->id == saa7164_v4l2_ctrls[i]) - return fill_queryctrl(&port->encoder_params, c); - - if (c->id < saa7164_v4l2_ctrls[i]) - break; - } - - return -EINVAL; -} - static int saa7164_encoder_stop_port(struct saa7164_port *port) { struct saa7164_dev *dev = port->dev; @@ -1084,8 +747,10 @@ static int fops_open(struct file *file) if (NULL == fh) return -ENOMEM; - file->private_data = fh; fh->port = port; + v4l2_fh_init(&fh->fh, video_devdata(file)); + v4l2_fh_add(&fh->fh); + file->private_data = fh; return 0; } @@ -1106,7 +771,8 @@ static int fops_release(struct file *file) } } - file->private_data = NULL; + v4l2_fh_del(&fh->fh); + v4l2_fh_exit(&fh->fh); kfree(fh); return 0; @@ -1250,10 +916,11 @@ err: static unsigned int fops_poll(struct file *file, poll_table *wait) { + unsigned long req_events = poll_requested_events(wait); struct saa7164_encoder_fh *fh = (struct saa7164_encoder_fh *)file->private_data; struct saa7164_port *port = fh->port; - unsigned int mask = 0; + unsigned int mask = v4l2_ctrl_poll(file, wait); port->last_poll_msecs_diff = port->last_poll_msecs; port->last_poll_msecs = jiffies_to_msecs(jiffies); @@ -1263,26 +930,18 @@ static unsigned int fops_poll(struct file *file, poll_table *wait) saa7164_histogram_update(&port->poll_interval, port->last_poll_msecs_diff); - if (!video_is_registered(port->v4l_device)) - return -EIO; + if (!(req_events & (POLLIN | POLLRDNORM))) + return mask; if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { if (atomic_inc_return(&port->v4l_reader_count) == 1) { if (saa7164_encoder_initialize(port) < 0) - return -EINVAL; + return mask | POLLERR; saa7164_encoder_start_streaming(port); msleep(200); } } - /* blocking wait for buffer */ - if ((file->f_flags & O_NONBLOCK) == 0) { - if (wait_event_interruptible(port->wait_read, - saa7164_enc_next_buf(port))) { - return -ERESTARTSYS; - } - } - /* Pull the first buffer from the used list */ if (!list_empty(&port->list_buf_used.list)) mask |= POLLIN | POLLRDNORM; @@ -1290,6 +949,10 @@ static unsigned int fops_poll(struct file *file, poll_table *wait) return mask; } +static const struct v4l2_ctrl_ops saa7164_ctrl_ops = { + .s_ctrl = saa7164_s_ctrl, +}; + static const struct v4l2_file_operations mpeg_fops = { .owner = THIS_MODULE, .open = fops_open, @@ -1302,24 +965,21 @@ static const struct v4l2_file_operations mpeg_fops = { static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_s_std = vidioc_s_std, .vidioc_g_std = vidioc_g_std, - .vidioc_enum_input = vidioc_enum_input, + .vidioc_enum_input = saa7164_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_tuner = saa7164_g_tuner, + .vidioc_s_tuner = saa7164_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, - .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, - .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, - .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_fmt_vid_cap = vidioc_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_fmt_vid_cap, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; static struct video_device saa7164_mpeg_template = { @@ -1357,6 +1017,7 @@ static struct video_device *saa7164_encoder_alloc( int saa7164_encoder_register(struct saa7164_port *port) { struct saa7164_dev *dev = port->dev; + struct v4l2_ctrl_handler *hdl = &port->ctrl_handler; int result = -ENODEV; dprintk(DBGLVL_ENC, "%s()\n", __func__); @@ -1381,19 +1042,52 @@ int saa7164_encoder_register(struct saa7164_port *port) port->video_format = EU_VIDEO_FORMAT_MPEG_2; port->audio_format = 0; port->video_resolution = 0; - port->ctl_brightness = 127; - port->ctl_contrast = 66; - port->ctl_hue = 128; - port->ctl_saturation = 62; - port->ctl_sharpness = 8; - port->encoder_params.bitrate = ENCODER_DEF_BITRATE; - port->encoder_params.bitrate_peak = ENCODER_DEF_BITRATE; - port->encoder_params.bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; - port->encoder_params.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS; - port->encoder_params.ctl_mute = 0; - port->encoder_params.ctl_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3; - port->encoder_params.refdist = 1; - port->encoder_params.gop_size = SAA7164_ENCODER_DEFAULT_GOP_SIZE; + port->freq = SAA7164_TV_MIN_FREQ; + + v4l2_ctrl_handler_init(hdl, 14); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, 66); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_SATURATION, 0, 255, 1, 62); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_HUE, 0, 255, 1, 128); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_SHARPNESS, 0x0, 0x0f, 1, 8); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_AUDIO_MUTE, 0x0, 0x01, 1, 0); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_AUDIO_VOLUME, -83, 24, 1, 20); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE, + ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE, + 100000, ENCODER_DEF_BITRATE); + v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_STREAM_TYPE, + V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 0, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS); + v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_ASPECT, + V4L2_MPEG_VIDEO_ASPECT_221x100, 0, + V4L2_MPEG_VIDEO_ASPECT_4x3); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, 15); + v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_B_FRAMES, 1, 3, 1, 1); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, + ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE, + 100000, ENCODER_DEF_BITRATE); + if (hdl->error) { + result = hdl->error; + goto failed; + } + port->std = V4L2_STD_NTSC_M; if (port->encodernorm.id & V4L2_STD_525_60) @@ -1412,6 +1106,8 @@ int saa7164_encoder_register(struct saa7164_port *port) goto failed; } + port->v4l_device->ctrl_handler = hdl; + v4l2_ctrl_handler_setup(hdl); video_set_drvdata(port->v4l_device, port); result = video_register_device(port->v4l_device, VFL_TYPE_GRABBER, -1); @@ -1466,6 +1162,7 @@ void saa7164_encoder_unregister(struct saa7164_port *port) port->v4l_device = NULL; } + v4l2_ctrl_handler_free(&port->ctrl_handler); dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr); } diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c index 859fd03d82f9..ee54491459a6 100644 --- a/drivers/media/pci/saa7164/saa7164-vbi.c +++ b/drivers/media/pci/saa7164/saa7164-vbi.c @@ -21,20 +21,6 @@ #include "saa7164.h" -static struct saa7164_tvnorm saa7164_tvnorms[] = { - { - .name = "NTSC-M", - .id = V4L2_STD_NTSC_M, - }, { - .name = "NTSC-JP", - .id = V4L2_STD_NTSC_M_JP, - } -}; - -static const u32 saa7164_v4l2_ctrls[] = { - 0 -}; - /* Take the encoder configuration from the port struct and * flush it to the hardware. */ @@ -43,23 +29,13 @@ static void saa7164_vbi_configure(struct saa7164_port *port) struct saa7164_dev *dev = port->dev; dprintk(DBGLVL_VBI, "%s()\n", __func__); - port->vbi_params.width = port->width; - port->vbi_params.height = port->height; + port->vbi_params.width = port->enc_port->width; + port->vbi_params.height = port->enc_port->height; port->vbi_params.is_50hz = - (port->encodernorm.id & V4L2_STD_625_50) != 0; + (port->enc_port->encodernorm.id & V4L2_STD_625_50) != 0; /* Set up the DIF (enable it) for analog mode by default */ saa7164_api_initialize_dif(port); - - /* Configure the correct video standard */ -#if 0 - saa7164_api_configure_dif(port, port->encodernorm.id); -#endif - -#if 0 - /* Ensure the audio decoder is correct configured */ - saa7164_api_set_audio_std(port); -#endif dprintk(DBGLVL_VBI, "%s() ends\n", __func__); } @@ -186,468 +162,50 @@ static int saa7164_vbi_initialize(struct saa7164_port *port) static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) { struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - unsigned int i; - dprintk(DBGLVL_VBI, "%s(id=0x%x)\n", __func__, (u32)id); - - for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) { - if (id & saa7164_tvnorms[i].id) - break; - } - if (i == ARRAY_SIZE(saa7164_tvnorms)) - return -EINVAL; - - port->encodernorm = saa7164_tvnorms[i]; - port->std = id; - - /* Update the audio decoder while is not running in - * auto detect mode. - */ - saa7164_api_set_audio_std(port); - - dprintk(DBGLVL_VBI, "%s(id=0x%x) OK\n", __func__, (u32)id); - - return 0; + return saa7164_s_std(fh->port->enc_port, id); } static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) { struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - *id = port->std; - return 0; -} - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - int n; - - char *inputs[] = { "tuner", "composite", "svideo", "aux", - "composite 2", "svideo 2", "aux 2" }; - - if (i->index >= 7) - return -EINVAL; - - strcpy(i->name, inputs[i->index]); - - if (i->index == 0) - i->type = V4L2_INPUT_TYPE_TUNER; - else - i->type = V4L2_INPUT_TYPE_CAMERA; - - for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++) - i->std |= saa7164_tvnorms[n].id; - - return 0; + return saa7164_g_std(fh->port->enc_port, id); } static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - if (saa7164_api_get_videomux(port) != SAA_OK) - return -EIO; - - *i = (port->mux_input - 1); - - dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, *i); - return 0; + return saa7164_g_input(fh->port->enc_port, i); } static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, i); - - if (i >= 7) - return -EINVAL; - - port->mux_input = i + 1; - if (saa7164_api_set_videomux(port) != SAA_OK) - return -EIO; - - return 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - if (0 != t->index) - return -EINVAL; - - strcpy(t->name, "tuner"); - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO; - - dprintk(DBGLVL_VBI, "VIDIOC_G_TUNER: tuner type %d\n", t->type); - - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - const struct v4l2_tuner *t) -{ - /* Update the A/V core */ - return 0; + return saa7164_s_input(fh->port->enc_port, i); } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - f->type = V4L2_TUNER_ANALOG_TV; - f->frequency = port->freq; - - return 0; + return saa7164_g_frequency(fh->port->enc_port, f); } static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - struct saa7164_port *tsport; - struct dvb_frontend *fe; - - /* TODO: Pull this for the std */ - struct analog_parameters params = { - .mode = V4L2_TUNER_ANALOG_TV, - .audmode = V4L2_TUNER_MODE_STEREO, - .std = port->encodernorm.id, - .frequency = f->frequency - }; - - /* Stop the encoder */ - dprintk(DBGLVL_VBI, "%s() frequency=%d tuner=%d\n", __func__, - f->frequency, f->tuner); - - if (f->tuner != 0) - return -EINVAL; - - if (f->type != V4L2_TUNER_ANALOG_TV) - return -EINVAL; - - port->freq = f->frequency; - - /* Update the hardware */ - if (port->nr == SAA7164_PORT_VBI1) - tsport = &dev->ports[SAA7164_PORT_TS1]; - else - if (port->nr == SAA7164_PORT_VBI2) - tsport = &dev->ports[SAA7164_PORT_TS2]; - else - BUG(); - - fe = tsport->dvb.frontend; - - if (fe && fe->ops.tuner_ops.set_analog_params) - fe->ops.tuner_ops.set_analog_params(fe, ¶ms); - else - printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__); - - saa7164_vbi_initialize(port); - - return 0; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__, - ctl->id, ctl->value); - - switch (ctl->id) { - case V4L2_CID_BRIGHTNESS: - ctl->value = port->ctl_brightness; - break; - case V4L2_CID_CONTRAST: - ctl->value = port->ctl_contrast; - break; - case V4L2_CID_SATURATION: - ctl->value = port->ctl_saturation; - break; - case V4L2_CID_HUE: - ctl->value = port->ctl_hue; - break; - case V4L2_CID_SHARPNESS: - ctl->value = port->ctl_sharpness; - break; - case V4L2_CID_AUDIO_VOLUME: - ctl->value = port->ctl_volume; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - int ret = 0; - - dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__, - ctl->id, ctl->value); - - switch (ctl->id) { - case V4L2_CID_BRIGHTNESS: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_brightness = ctl->value; - saa7164_api_set_usercontrol(port, - PU_BRIGHTNESS_CONTROL); - } else - ret = -EINVAL; - break; - case V4L2_CID_CONTRAST: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_contrast = ctl->value; - saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL); - } else - ret = -EINVAL; - break; - case V4L2_CID_SATURATION: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_saturation = ctl->value; - saa7164_api_set_usercontrol(port, - PU_SATURATION_CONTROL); - } else - ret = -EINVAL; - break; - case V4L2_CID_HUE: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_hue = ctl->value; - saa7164_api_set_usercontrol(port, PU_HUE_CONTROL); - } else - ret = -EINVAL; - break; - case V4L2_CID_SHARPNESS: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_sharpness = ctl->value; - saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL); - } else - ret = -EINVAL; - break; - case V4L2_CID_AUDIO_VOLUME: - if ((ctl->value >= -83) && (ctl->value <= 24)) { - port->ctl_volume = ctl->value; - saa7164_api_set_audio_volume(port, port->ctl_volume); - } else - ret = -EINVAL; - break; - default: - ret = -EINVAL; - } + int ret = saa7164_s_frequency(fh->port->enc_port, f); + if (ret == 0) + saa7164_vbi_initialize(fh->port); return ret; } -static int saa7164_get_ctrl(struct saa7164_port *port, - struct v4l2_ext_control *ctrl) -{ - struct saa7164_vbi_params *params = &port->vbi_params; - - switch (ctrl->id) { - case V4L2_CID_MPEG_STREAM_TYPE: - ctrl->value = params->stream_type; - break; - case V4L2_CID_MPEG_AUDIO_MUTE: - ctrl->value = params->ctl_mute; - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - ctrl->value = params->ctl_aspect; - break; - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - ctrl->value = params->refdist; - break; - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - ctrl->value = params->gop_size; - break; - default: - return -EINVAL; - } - return 0; -} - -static int vidioc_g_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = saa7164_get_ctrl(port, ctrl); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - - } - - return -EINVAL; -} - -static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3) -{ - int ret = -EINVAL; - - switch (ctrl->id) { - case V4L2_CID_MPEG_STREAM_TYPE: - if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) || - (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)) - ret = 0; - break; - case V4L2_CID_MPEG_AUDIO_MUTE: - if ((ctrl->value >= 0) && - (ctrl->value <= 1)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) && - (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - if ((ctrl->value >= 0) && - (ctrl->value <= 255)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - if ((ctrl->value >= 1) && - (ctrl->value <= 3)) - ret = 0; - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int vidioc_try_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = saa7164_try_ctrl(ctrl, 0); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - } - - return -EINVAL; -} - -static int saa7164_set_ctrl(struct saa7164_port *port, - struct v4l2_ext_control *ctrl) -{ - struct saa7164_vbi_params *params = &port->vbi_params; - int ret = 0; - - switch (ctrl->id) { - case V4L2_CID_MPEG_STREAM_TYPE: - params->stream_type = ctrl->value; - break; - case V4L2_CID_MPEG_AUDIO_MUTE: - params->ctl_mute = ctrl->value; - ret = saa7164_api_audio_mute(port, params->ctl_mute); - if (ret != SAA_OK) { - printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, - ret); - ret = -EIO; - } - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - params->ctl_aspect = ctrl->value; - ret = saa7164_api_set_aspect_ratio(port); - if (ret != SAA_OK) { - printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, - ret); - ret = -EIO; - } - break; - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - params->refdist = ctrl->value; - break; - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - params->gop_size = ctrl->value; - break; - default: - return -EINVAL; - } - - /* TODO: Update the hardware */ - - return ret; -} - -static int vidioc_s_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = saa7164_try_ctrl(ctrl, 0); - if (err) { - ctrls->error_idx = i; - break; - } - err = saa7164_set_ctrl(port, ctrl); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - - } - - return -EINVAL; -} - static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { @@ -672,144 +230,6 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (f->index != 0) - return -EINVAL; - - strlcpy(f->description, "VBI", sizeof(f->description)); - f->pixelformat = V4L2_PIX_FMT_MPEG; - - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - port->ts_packet_size * port->ts_packet_count; - f->fmt.pix.colorspace = 0; - f->fmt.pix.width = port->width; - f->fmt.pix.height = port->height; - - dprintk(DBGLVL_VBI, "VIDIOC_G_FMT: w: %d, h: %d\n", - port->width, port->height); - - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - port->ts_packet_size * port->ts_packet_count; - f->fmt.pix.colorspace = 0; - dprintk(DBGLVL_VBI, "VIDIOC_TRY_FMT: w: %d, h: %d\n", - port->width, port->height); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct saa7164_vbi_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - port->ts_packet_size * port->ts_packet_count; - f->fmt.pix.colorspace = 0; - - dprintk(DBGLVL_VBI, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", - f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); - - return 0; -} - -static int fill_queryctrl(struct saa7164_vbi_params *params, - struct v4l2_queryctrl *c) -{ - switch (c->id) { - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127); - case V4L2_CID_CONTRAST: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66); - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128); - case V4L2_CID_SHARPNESS: - return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8); - case V4L2_CID_MPEG_AUDIO_MUTE: - return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0); - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(c, -83, 24, 1, 20); - case V4L2_CID_MPEG_STREAM_TYPE: - return v4l2_ctrl_query_fill(c, - V4L2_MPEG_STREAM_TYPE_MPEG2_PS, - V4L2_MPEG_STREAM_TYPE_MPEG2_TS, - 1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS); - case V4L2_CID_MPEG_VIDEO_ASPECT: - return v4l2_ctrl_query_fill(c, - V4L2_MPEG_VIDEO_ASPECT_1x1, - V4L2_MPEG_VIDEO_ASPECT_221x100, - 1, V4L2_MPEG_VIDEO_ASPECT_4x3); - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - return v4l2_ctrl_query_fill(c, 1, 255, 1, 15); - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - return v4l2_ctrl_query_fill(c, - 1, 3, 1, 1); - default: - return -EINVAL; - } -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *c) -{ - struct saa7164_vbi_fh *fh = priv; - struct saa7164_port *port = fh->port; - int i, next; - u32 id = c->id; - - memset(c, 0, sizeof(*c)); - - next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL); - c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL; - - for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) { - if (next) { - if (c->id < saa7164_v4l2_ctrls[i]) - c->id = saa7164_v4l2_ctrls[i]; - else - continue; - } - - if (c->id == saa7164_v4l2_ctrls[i]) - return fill_queryctrl(&port->vbi_params, c); - - if (c->id < saa7164_v4l2_ctrls[i]) - break; - } - - return -EINVAL; -} - static int saa7164_vbi_stop_port(struct saa7164_port *port) { struct saa7164_dev *dev = port->dev; @@ -999,7 +419,6 @@ static int saa7164_vbi_fmt(struct file *file, void *priv, struct v4l2_format *f) { /* ntsc */ - f->fmt.vbi.samples_per_line = 1600; f->fmt.vbi.samples_per_line = 1440; f->fmt.vbi.sampling_rate = 27000000; f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; @@ -1009,6 +428,7 @@ static int saa7164_vbi_fmt(struct file *file, void *priv, f->fmt.vbi.count[0] = 18; f->fmt.vbi.start[1] = 263 + 10 + 1; f->fmt.vbi.count[1] = 18; + memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved)); return 0; } @@ -1031,8 +451,10 @@ static int fops_open(struct file *file) if (NULL == fh) return -ENOMEM; - file->private_data = fh; fh->port = port; + v4l2_fh_init(&fh->fh, video_devdata(file)); + v4l2_fh_add(&fh->fh); + file->private_data = fh; return 0; } @@ -1053,7 +475,8 @@ static int fops_release(struct file *file) } } - file->private_data = NULL; + v4l2_fh_del(&fh->fh); + v4l2_fh_exit(&fh->fh); kfree(fh); return 0; @@ -1248,24 +671,14 @@ static const struct v4l2_file_operations vbi_fops = { static const struct v4l2_ioctl_ops vbi_ioctl_ops = { .vidioc_s_std = vidioc_s_std, .vidioc_g_std = vidioc_g_std, - .vidioc_enum_input = vidioc_enum_input, + .vidioc_enum_input = saa7164_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_tuner = saa7164_g_tuner, + .vidioc_s_tuner = saa7164_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, - .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, - .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, - .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_fmt_vbi_cap = saa7164_vbi_fmt, .vidioc_try_fmt_vbi_cap = saa7164_vbi_fmt, .vidioc_s_fmt_vbi_cap = saa7164_vbi_fmt, @@ -1335,7 +748,7 @@ int saa7164_vbi_register(struct saa7164_port *port) goto failed; } - port->std = V4L2_STD_NTSC_M; + port->enc_port = &dev->ports[port->nr - 2]; video_set_drvdata(port->v4l_device, port); result = video_register_device(port->v4l_device, VFL_TYPE_VBI, -1); diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h index 18906e0c80e1..8337524bfb8c 100644 --- a/drivers/media/pci/saa7164/saa7164.h +++ b/drivers/media/pci/saa7164/saa7164.h @@ -54,8 +54,6 @@ #include <media/tuner.h> #include <media/tveeprom.h> -#include <media/videobuf-dma-sg.h> -#include <media/videobuf-dvb.h> #include <dvb_demux.h> #include <dvb_frontend.h> #include <dvb_net.h> @@ -64,6 +62,8 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-device.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-event.h> #include "saa7164-reg.h" #include "saa7164-types.h" @@ -117,7 +117,11 @@ #define DBGLVL_CPU 8192 #define SAA7164_NORMS \ - (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443) + (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP) + +/* TV frequency range copied from tuner-core.c */ +#define SAA7164_TV_MIN_FREQ (44U * 16U) +#define SAA7164_TV_MAX_FREQ (958U * 16U) enum port_t { SAA7164_MPEG_UNDEFINED = 0, @@ -185,11 +189,13 @@ struct saa7164_subid { }; struct saa7164_encoder_fh { + struct v4l2_fh fh; struct saa7164_port *port; atomic_t v4l_reading; }; struct saa7164_vbi_fh { + struct v4l2_fh fh; struct saa7164_port *port; atomic_t v4l_reading; }; @@ -381,12 +387,11 @@ struct saa7164_port { /* Encoder */ /* Defaults established in saa7164-encoder.c */ struct saa7164_tvnorm encodernorm; + struct v4l2_ctrl_handler ctrl_handler; v4l2_std_id std; u32 height; u32 width; u32 freq; - u32 ts_packet_size; - u32 ts_packet_count; u8 mux_input; u8 encoder_profile; u8 video_format; @@ -419,6 +424,7 @@ struct saa7164_port { /* V4L VBI */ struct tmComResVBIFormatDescrHeader vbi_fmt_ntsc; struct saa7164_vbi_params vbi_params; + struct saa7164_port *enc_port; /* Debug */ u32 sync_errors; @@ -594,6 +600,16 @@ extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i); /* ----------------------------------------------------------- */ /* saa7164-encoder.c */ +int saa7164_s_std(struct saa7164_port *port, v4l2_std_id id); +int saa7164_g_std(struct saa7164_port *port, v4l2_std_id *id); +int saa7164_enum_input(struct file *file, void *priv, struct v4l2_input *i); +int saa7164_g_input(struct saa7164_port *port, unsigned int *i); +int saa7164_s_input(struct saa7164_port *port, unsigned int i); +int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t); +int saa7164_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t); +int saa7164_g_frequency(struct saa7164_port *port, struct v4l2_frequency *f); +int saa7164_s_frequency(struct saa7164_port *port, + const struct v4l2_frequency *f); int saa7164_encoder_register(struct saa7164_port *port); void saa7164_encoder_unregister(struct saa7164_port *port); diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c index 53fff5425c13..4432fd69b7cb 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c @@ -458,11 +458,12 @@ static inline u32 vop_usec(const vop_header *vh) static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, struct vb2_buffer *vb, const vop_header *vh) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct solo_dev *solo_dev = solo_enc->solo_dev; - struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); + struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); int frame_size; - vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; + vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME; if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len) return -EIO; @@ -470,7 +471,7 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN); vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len); - return solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf, + return solo_send_desc(solo_enc, solo_enc->jpeg_len, sgt, vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev), frame_size, SOLO_JPEG_EXT_ADDR(solo_dev), SOLO_JPEG_EXT_SIZE(solo_dev)); @@ -479,8 +480,9 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, struct vb2_buffer *vb, const vop_header *vh) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct solo_dev *solo_dev = solo_enc->solo_dev; - struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); + struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); int frame_off, frame_size; int skip = 0; @@ -488,15 +490,15 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, return -EIO; /* If this is a key frame, add extra header */ - vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME | + vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME); if (!vop_type(vh)) { skip = solo_enc->vop_len; - vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; + vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME; vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) + solo_enc->vop_len); } else { - vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; + vbuf->flags |= V4L2_BUF_FLAG_PFRAME; vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh)); } @@ -505,7 +507,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev); frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN); - return solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size, + return solo_send_desc(solo_enc, skip, sgt, frame_off, frame_size, SOLO_MP4E_EXT_ADDR(solo_dev), SOLO_MP4E_EXT_SIZE(solo_dev)); } @@ -513,6 +515,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc, struct vb2_buffer *vb, struct solo_enc_buf *enc_buf) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); const vop_header *vh = enc_buf->vh; int ret; @@ -527,17 +530,18 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc, } if (!ret) { - vb->v4l2_buf.sequence = solo_enc->sequence++; - vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh); - vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh); + vbuf->sequence = solo_enc->sequence++; + vbuf->timestamp.tv_sec = vop_sec(vh); + vbuf->timestamp.tv_usec = vop_usec(vh); /* Check for motion flags */ if (solo_is_motion_on(solo_enc) && enc_buf->motion) { struct v4l2_event ev = { .type = V4L2_EVENT_MOTION_DET, .u.motion_det = { - .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ, - .frame_sequence = vb->v4l2_buf.sequence, + .flags + = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ, + .frame_sequence = vbuf->sequence, .region_mask = enc_buf->motion ? 1 : 0, }, }; @@ -571,7 +575,7 @@ static void solo_enc_handle_one(struct solo_enc_dev *solo_enc, list_del(&vb->list); spin_unlock_irqrestore(&solo_enc->av_lock, flags); - solo_enc_fillbuf(solo_enc, &vb->vb, enc_buf); + solo_enc_fillbuf(solo_enc, &vb->vb.vb2_buf, enc_buf); unlock: mutex_unlock(&solo_enc->lock); } @@ -659,7 +663,7 @@ static int solo_ring_thread(void *data) } static int solo_enc_queue_setup(struct vb2_queue *q, - const struct v4l2_format *fmt, + const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) @@ -678,10 +682,11 @@ static int solo_enc_queue_setup(struct vb2_queue *q, static void solo_enc_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq); struct solo_vb2_buf *solo_vb = - container_of(vb, struct solo_vb2_buf, vb); + container_of(vbuf, struct solo_vb2_buf, vb); spin_lock(&solo_enc->av_lock); list_add_tail(&solo_vb->list, &solo_enc->vidq_active); @@ -734,25 +739,26 @@ static void solo_enc_stop_streaming(struct vb2_queue *q) struct solo_vb2_buf, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&solo_enc->av_lock, flags); } static void solo_enc_buf_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vb->vb2_queue); - struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); + struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); switch (solo_enc->fmt) { case V4L2_PIX_FMT_MPEG4: case V4L2_PIX_FMT_H264: - if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) - sg_copy_from_buffer(vbuf->sgl, vbuf->nents, + if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME) + sg_copy_from_buffer(sgt->sgl, sgt->nents, solo_enc->vop, solo_enc->vop_len); break; default: /* V4L2_PIX_FMT_MJPEG */ - sg_copy_from_buffer(vbuf->sgl, vbuf->nents, + sg_copy_from_buffer(sgt->sgl, sgt->nents, solo_enc->jpeg_header, solo_enc->jpeg_len); break; } @@ -1291,7 +1297,7 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, solo_enc->vidq.ops = &solo_enc_video_qops; solo_enc->vidq.mem_ops = &vb2_dma_sg_memops; solo_enc->vidq.drv_priv = solo_enc; - solo_enc->vidq.gfp_flags = __GFP_DMA32; + solo_enc->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM; solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf); solo_enc->vidq.lock = &solo_enc->lock; diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c index 63ae8a61f603..f7ce493b1fee 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c @@ -26,6 +26,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-common.h> #include <media/v4l2-event.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "solo6x10.h" @@ -191,13 +192,14 @@ static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch) static void solo_fillbuf(struct solo_dev *solo_dev, struct vb2_buffer *vb) { - dma_addr_t vbuf; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + dma_addr_t addr; unsigned int fdma_addr; int error = -1; int i; - vbuf = vb2_dma_contig_plane_dma_addr(vb, 0); - if (!vbuf) + addr = vb2_dma_contig_plane_dma_addr(vb, 0); + if (!addr) goto finish_buf; if (erase_off(solo_dev)) { @@ -213,7 +215,7 @@ static void solo_fillbuf(struct solo_dev *solo_dev, fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write * (SOLO_HW_BPL * solo_vlines(solo_dev))); - error = solo_p2m_dma_t(solo_dev, 0, vbuf, fdma_addr, + error = solo_p2m_dma_t(solo_dev, 0, addr, fdma_addr, solo_bytesperline(solo_dev), solo_vlines(solo_dev), SOLO_HW_BPL); } @@ -222,8 +224,8 @@ finish_buf: if (!error) { vb2_set_plane_payload(vb, 0, solo_vlines(solo_dev) * solo_bytesperline(solo_dev)); - vb->v4l2_buf.sequence = solo_dev->sequence++; - v4l2_get_timestamp(&vb->v4l2_buf.timestamp); + vbuf->sequence = solo_dev->sequence++; + v4l2_get_timestamp(&vbuf->timestamp); } vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); @@ -256,7 +258,7 @@ static void solo_thread_try(struct solo_dev *solo_dev) spin_unlock(&solo_dev->slock); - solo_fillbuf(solo_dev, &vb->vb); + solo_fillbuf(solo_dev, &vb->vb.vb2_buf); } assert_spin_locked(&solo_dev->slock); @@ -311,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 struct v4l2_format *fmt, +static int solo_queue_setup(struct vb2_queue *q, const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -345,10 +347,11 @@ static void solo_stop_streaming(struct vb2_queue *q) static void solo_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; struct solo_dev *solo_dev = vb2_get_drv_priv(vq); struct solo_vb2_buf *solo_vb = - container_of(vb, struct solo_vb2_buf, vb); + container_of(vbuf, struct solo_vb2_buf, vb); spin_lock(&solo_dev->slock); list_add_tail(&solo_vb->list, &solo_dev->vidq_active); @@ -675,7 +678,7 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr) solo_dev->vidq.mem_ops = &vb2_dma_contig_memops; solo_dev->vidq.drv_priv = solo_dev; solo_dev->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - solo_dev->vidq.gfp_flags = __GFP_DMA32; + solo_dev->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM; solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf); solo_dev->vidq.lock = &solo_dev->lock; ret = vb2_queue_init(&solo_dev->vidq); diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h index 27423d7f5410..4ab6586c0467 100644 --- a/drivers/media/pci/solo6x10/solo6x10.h +++ b/drivers/media/pci/solo6x10/solo6x10.h @@ -35,7 +35,7 @@ #include <media/v4l2-dev.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include "solo6x10-regs.h" @@ -135,7 +135,7 @@ struct solo_p2m_dev { #define OSD_TEXT_MAX 44 struct solo_vb2_buf { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 59b3a36a3639..6367b455a7e7 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -88,11 +88,11 @@ struct vip_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; dma_addr_t dma; }; -static inline struct vip_buffer *to_vip_buffer(struct vb2_buffer *vb2) +static inline struct vip_buffer *to_vip_buffer(struct vb2_v4l2_buffer *vb2) { return container_of(vb2, struct vip_buffer, vb); } @@ -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 struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *vq, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -287,7 +287,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, }; static int buffer_init(struct vb2_buffer *vb) { - struct vip_buffer *vip_buf = to_vip_buffer(vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct vip_buffer *vip_buf = to_vip_buffer(vbuf); vip_buf->dma = vb2_dma_contig_plane_dma_addr(vb, 0); INIT_LIST_HEAD(&vip_buf->list); @@ -296,8 +297,9 @@ static int buffer_init(struct vb2_buffer *vb) static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue); - struct vip_buffer *vip_buf = to_vip_buffer(vb); + struct vip_buffer *vip_buf = to_vip_buffer(vbuf); unsigned long size; size = vip->format.sizeimage; @@ -307,14 +309,15 @@ static int buffer_prepare(struct vb2_buffer *vb) return -EINVAL; } - vb2_set_plane_payload(&vip_buf->vb, 0, size); + vb2_set_plane_payload(&vip_buf->vb.vb2_buf, 0, size); return 0; } static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue); - struct vip_buffer *vip_buf = to_vip_buffer(vb); + struct vip_buffer *vip_buf = to_vip_buffer(vbuf); spin_lock(&vip->lock); list_add_tail(&vip_buf->list, &vip->buffer_list); @@ -329,8 +332,9 @@ static void buffer_queue(struct vb2_buffer *vb) } static void buffer_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue); - struct vip_buffer *vip_buf = to_vip_buffer(vb); + struct vip_buffer *vip_buf = to_vip_buffer(vbuf); /* Buffer handled, remove it from the list */ spin_lock(&vip->lock); @@ -370,7 +374,7 @@ static void stop_streaming(struct vb2_queue *vq) /* Release all active buffers */ spin_lock(&vip->lock); list_for_each_entry_safe(vip_buf, node, &vip->buffer_list, list) { - vb2_buffer_done(&vip_buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&vip_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); list_del(&vip_buf->list); } spin_unlock(&vip->lock); @@ -813,9 +817,9 @@ 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.v4l2_buf.timestamp); - vip->active->vb.v4l2_buf.sequence = vip->sequence++; - vb2_buffer_done(&vip->active->vb, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&vip->active->vb.timestamp); + vip->active->vb.sequence = vip->sequence++; + vb2_buffer_done(&vip->active->vb.vb2_buf, VB2_BUF_STATE_DONE); } return IRQ_HANDLED; diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index 3f24fce74fc1..f89364951ebd 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -303,7 +303,6 @@ static int arm_thread(void *data) static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len, u8 *buffer2, size_t buffer2_len, struct dvb_demux_filter *dvbdmxfilter, - enum dmx_success success, struct av7110 *av7110) { if (!dvbdmxfilter->feed->demux->dmx.frontend) @@ -329,16 +328,14 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len, } return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len, buffer2, buffer2_len, - &dvbdmxfilter->filter, - DMX_OK); + &dvbdmxfilter->filter); case DMX_TYPE_TS: if (!(dvbdmxfilter->feed->ts_type & TS_PACKET)) return 0; if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY) return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len, buffer2, buffer2_len, - &dvbdmxfilter->feed->feed.ts, - DMX_OK); + &dvbdmxfilter->feed->feed.ts); else av7110_p2t_write(buffer1, buffer1_len, dvbdmxfilter->feed->pid, @@ -422,7 +419,7 @@ static void debiirq(unsigned long cookie) DvbDmxFilterCallback((u8 *)av7110->debi_virt, av7110->debilen, NULL, 0, av7110->handle2filter[handle], - DMX_OK, av7110); + av7110); xfer = RX_BUFF; break; diff --git a/drivers/media/pci/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c index 9544cfc06601..9ed1ec7d3551 100644 --- a/drivers/media/pci/ttpci/av7110_av.c +++ b/drivers/media/pci/ttpci/av7110_av.c @@ -102,7 +102,7 @@ int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len) buf[4] = buf[5] = 0; if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY) return dvbdmxfeed->cb.ts(buf, len, NULL, 0, - &dvbdmxfeed->feed.ts, DMX_OK); + &dvbdmxfeed->feed.ts); else return dvb_filter_pes2ts(p2t, buf, len, 1); } @@ -112,7 +112,7 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data) struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv; dvbdmxfeed->cb.ts(data, 188, NULL, 0, - &dvbdmxfeed->feed.ts, DMX_OK); + &dvbdmxfeed->feed.ts); return 0; } @@ -815,7 +815,7 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, memcpy(obuf + l, buf + c, TS_SIZE - l); c = length; } - feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts, DMX_OK); + feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts); pes_start = 0; } } diff --git a/drivers/media/pci/tw68/tw68-core.c b/drivers/media/pci/tw68/tw68-core.c index 04706cc9b818..4e77618fbb2b 100644 --- a/drivers/media/pci/tw68/tw68-core.c +++ b/drivers/media/pci/tw68/tw68-core.c @@ -257,9 +257,9 @@ static int tw68_initdev(struct pci_dev *pci_dev, dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat, (u64)pci_resource_start(pci_dev, 0)); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev, DMA_BIT_MASK(32))) { + err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32)); + if (err) { pr_info("%s: Oops: no 32bit PCI DMA ???\n", dev->name); - err = -EIO; goto fail1; } diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c index 8355e55b4e8e..46642ef9151b 100644 --- a/drivers/media/pci/tw68/tw68-video.c +++ b/drivers/media/pci/tw68/tw68-video.c @@ -376,10 +376,11 @@ static int tw68_buffer_count(unsigned int size, unsigned int count) /* ------------------------------------------------------------- */ /* vb2 queue operations */ -static int tw68_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, +static int tw68_queue_setup(struct vb2_queue *q, const void *parg, 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; @@ -423,9 +424,10 @@ static int tw68_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, */ static void tw68_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; struct tw68_dev *dev = vb2_get_drv_priv(vq); - struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb); + struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb); struct tw68_buf *prev; unsigned long flags; @@ -457,9 +459,10 @@ static void tw68_buf_queue(struct vb2_buffer *vb) */ static int tw68_buf_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; struct tw68_dev *dev = vb2_get_drv_priv(vq); - struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb); + struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb); struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0); unsigned size, bpl; @@ -499,9 +502,10 @@ static int tw68_buf_prepare(struct vb2_buffer *vb) static void tw68_buf_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; struct tw68_dev *dev = vb2_get_drv_priv(vq); - struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb); + struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb); pci_free_consistent(dev->pci, buf->size, buf->cpu, buf->dma); } @@ -528,7 +532,7 @@ static void tw68_stop_streaming(struct vb2_queue *q) container_of(dev->active.next, struct tw68_buf, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } } @@ -975,7 +979,7 @@ int tw68_video_init2(struct tw68_dev *dev, int video_nr) dev->vidq.ops = &tw68_video_qops; dev->vidq.mem_ops = &vb2_dma_sg_memops; dev->vidq.drv_priv = dev; - dev->vidq.gfp_flags = __GFP_DMA32; + dev->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM; dev->vidq.buf_struct_size = sizeof(struct tw68_buf); dev->vidq.lock = &dev->lock; dev->vidq.min_buffers_needed = 2; @@ -1012,10 +1016,10 @@ 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.v4l2_buf.timestamp); - buf->vb.v4l2_buf.field = dev->field; - buf->vb.v4l2_buf.sequence = dev->seqnr++; - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.field = dev->field; + buf->vb.sequence = dev->seqnr++; + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); status &= ~(TW68_DMAPI); if (0 == status) return; diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h index ef51e4d48866..6c7dcb300f34 100644 --- a/drivers/media/pci/tw68/tw68.h +++ b/drivers/media/pci/tw68/tw68.h @@ -36,6 +36,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-sg.h> #include "tw68-reg.h" @@ -118,7 +119,7 @@ struct tw68_dev; /* forward delclaration */ /* buffer for one video/vbi/ts frame */ struct tw68_buf { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; unsigned int size; diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index dc75694ac12d..ccbc9742cb7a 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -233,7 +233,7 @@ config VIDEO_SH_VEU config VIDEO_RENESAS_JPU tristate "Renesas JPEG Processing Unit" - depends on VIDEO_DEV && VIDEO_V4L2 + depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA depends on ARCH_SHMOBILE || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index c8447fa3fd91..f0480d687f17 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -307,7 +307,8 @@ static inline struct vpfe_device *to_vpfe(struct vpfe_ccdc *ccdc) return container_of(ccdc, struct vpfe_device, ccdc); } -static inline struct vpfe_cap_buffer *to_vpfe_buffer(struct vb2_buffer *vb) +static inline +struct vpfe_cap_buffer *to_vpfe_buffer(struct vb2_v4l2_buffer *vb) { return container_of(vb, struct vpfe_cap_buffer, vb); } @@ -1257,14 +1258,14 @@ static inline void vpfe_schedule_next_buffer(struct vpfe_device *vpfe) list_del(&vpfe->next_frm->list); vpfe_set_sdr_addr(&vpfe->ccdc, - vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb, 0)); + vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb.vb2_buf, 0)); } static inline void vpfe_schedule_bottom_field(struct vpfe_device *vpfe) { unsigned long addr; - addr = vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb, 0) + + addr = vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb.vb2_buf, 0) + vpfe->field_off; vpfe_set_sdr_addr(&vpfe->ccdc, addr); @@ -1280,10 +1281,10 @@ 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.v4l2_buf.timestamp); - vpfe->cur_frm->vb.v4l2_buf.field = vpfe->fmt.fmt.pix.field; - vpfe->cur_frm->vb.v4l2_buf.sequence = vpfe->sequence++; - vb2_buffer_done(&vpfe->cur_frm->vb, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&vpfe->cur_frm->vb.timestamp); + 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); vpfe->cur_frm = vpfe->next_frm; } @@ -1907,10 +1908,11 @@ 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 struct v4l2_format *fmt, + 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) @@ -1942,6 +1944,7 @@ static int vpfe_queue_setup(struct vb2_queue *vq, */ static int vpfe_buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vpfe_device *vpfe = vb2_get_drv_priv(vb->vb2_queue); vb2_set_plane_payload(vb, 0, vpfe->fmt.fmt.pix.sizeimage); @@ -1949,7 +1952,7 @@ static int vpfe_buffer_prepare(struct vb2_buffer *vb) if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) return -EINVAL; - vb->v4l2_buf.field = vpfe->fmt.fmt.pix.field; + vbuf->field = vpfe->fmt.fmt.pix.field; return 0; } @@ -1960,8 +1963,9 @@ static int vpfe_buffer_prepare(struct vb2_buffer *vb) */ static void vpfe_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vpfe_device *vpfe = vb2_get_drv_priv(vb->vb2_queue); - struct vpfe_cap_buffer *buf = to_vpfe_buffer(vb); + struct vpfe_cap_buffer *buf = to_vpfe_buffer(vbuf); unsigned long flags = 0; /* add the buffer to the DMA queue */ @@ -2006,7 +2010,7 @@ static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count) list_del(&vpfe->cur_frm->list); spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags); - addr = vb2_dma_contig_plane_dma_addr(&vpfe->cur_frm->vb, 0); + addr = vb2_dma_contig_plane_dma_addr(&vpfe->cur_frm->vb.vb2_buf, 0); vpfe_set_sdr_addr(&vpfe->ccdc, (unsigned long)(addr)); @@ -2023,7 +2027,7 @@ static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count) err: list_for_each_entry_safe(buf, tmp, &vpfe->dma_queue, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); } return ret; @@ -2055,13 +2059,14 @@ static void vpfe_stop_streaming(struct vb2_queue *vq) /* release all active buffers */ spin_lock_irqsave(&vpfe->dma_queue_lock, flags); if (vpfe->cur_frm == vpfe->next_frm) { - vb2_buffer_done(&vpfe->cur_frm->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&vpfe->cur_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); } else { if (vpfe->cur_frm != NULL) - vb2_buffer_done(&vpfe->cur_frm->vb, + vb2_buffer_done(&vpfe->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); if (vpfe->next_frm != NULL) - vb2_buffer_done(&vpfe->next_frm->vb, + vb2_buffer_done(&vpfe->next_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); } @@ -2069,7 +2074,8 @@ static void vpfe_stop_streaming(struct vb2_queue *vq) vpfe->next_frm = list_entry(vpfe->dma_queue.next, struct vpfe_cap_buffer, list); list_del(&vpfe->next_frm->list); - vb2_buffer_done(&vpfe->next_frm->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&vpfe->next_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags); } @@ -2546,11 +2552,12 @@ static int vpfe_probe(struct platform_device *pdev) if (IS_ERR(ccdc->ccdc_cfg.base_addr)) return PTR_ERR(ccdc->ccdc_cfg.base_addr); - vpfe->irq = platform_get_irq(pdev, 0); - if (vpfe->irq <= 0) { + ret = platform_get_irq(pdev, 0); + if (ret <= 0) { dev_err(&pdev->dev, "No IRQ resource\n"); return -ENODEV; } + vpfe->irq = ret; ret = devm_request_irq(vpfe->pdev, vpfe->irq, vpfe_isr, 0, "vpfe_capture0", vpfe); diff --git a/drivers/media/platform/am437x/am437x-vpfe.h b/drivers/media/platform/am437x/am437x-vpfe.h index 5bfb35649a39..777bf97fea57 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.h +++ b/drivers/media/platform/am437x/am437x-vpfe.h @@ -31,6 +31,7 @@ #include <media/v4l2-dev.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "am437x-vpfe_regs.h" @@ -104,7 +105,7 @@ struct vpfe_config { }; struct vpfe_cap_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index b7e70fb05eb8..7764b9c482ef 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c @@ -54,7 +54,7 @@ struct bcap_format { }; struct bcap_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; @@ -149,7 +149,7 @@ static const struct bcap_format bcap_formats[] = { static irqreturn_t bcap_isr(int irq, void *dev_id); -static struct bcap_buffer *to_bcap_vb(struct vb2_buffer *vb) +static struct bcap_buffer *to_bcap_vb(struct vb2_v4l2_buffer *vb) { return container_of(vb, struct bcap_buffer, vb); } @@ -202,10 +202,11 @@ static void bcap_free_sensor_formats(struct bcap_device *bcap_dev) } static int bcap_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + 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) @@ -223,6 +224,7 @@ static int bcap_queue_setup(struct vb2_queue *vq, static int bcap_buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); unsigned long size = bcap_dev->fmt.sizeimage; @@ -233,15 +235,16 @@ static int bcap_buffer_prepare(struct vb2_buffer *vb) } vb2_set_plane_payload(vb, 0, size); - vb->v4l2_buf.field = bcap_dev->fmt.field; + vbuf->field = bcap_dev->fmt.field; return 0; } static void bcap_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); - struct bcap_buffer *buf = to_bcap_vb(vb); + struct bcap_buffer *buf = to_bcap_vb(vbuf); unsigned long flags; spin_lock_irqsave(&bcap_dev->lock, flags); @@ -251,8 +254,9 @@ static void bcap_buffer_queue(struct vb2_buffer *vb) static void bcap_buffer_cleanup(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); - struct bcap_buffer *buf = to_bcap_vb(vb); + struct bcap_buffer *buf = to_bcap_vb(vbuf); unsigned long flags; spin_lock_irqsave(&bcap_dev->lock, flags); @@ -333,7 +337,8 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) struct bcap_buffer, list); /* remove buffer from the dma queue */ list_del_init(&bcap_dev->cur_frm->list); - addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); + addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb.vb2_buf, + 0); /* update DMA address */ ppi->ops->update_addr(ppi, (unsigned long)addr); /* enable ppi */ @@ -344,7 +349,7 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) err: list_for_each_entry_safe(buf, tmp, &bcap_dev->dma_queue, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); } return ret; @@ -367,13 +372,15 @@ static void bcap_stop_streaming(struct vb2_queue *vq) /* release all active buffers */ if (bcap_dev->cur_frm) - vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&bcap_dev->cur_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); while (!list_empty(&bcap_dev->dma_queue)) { bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, struct bcap_buffer, list); list_del_init(&bcap_dev->cur_frm->list); - vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&bcap_dev->cur_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); } } @@ -392,18 +399,19 @@ static irqreturn_t bcap_isr(int irq, void *dev_id) { struct ppi_if *ppi = dev_id; struct bcap_device *bcap_dev = ppi->priv; - struct vb2_buffer *vb = &bcap_dev->cur_frm->vb; + struct vb2_v4l2_buffer *vbuf = &bcap_dev->cur_frm->vb; + struct vb2_buffer *vb = &vbuf->vb2_buf; dma_addr_t addr; spin_lock(&bcap_dev->lock); if (!list_empty(&bcap_dev->dma_queue)) { - v4l2_get_timestamp(&vb->v4l2_buf.timestamp); + v4l2_get_timestamp(&vbuf->timestamp); if (ppi->err) { vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); ppi->err = false; } else { - vb->v4l2_buf.sequence = bcap_dev->sequence++; + vbuf->sequence = bcap_dev->sequence++; vb2_buffer_done(vb, VB2_BUF_STATE_DONE); } bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, @@ -420,7 +428,8 @@ static irqreturn_t bcap_isr(int irq, void *dev_id) if (bcap_dev->stop) { complete(&bcap_dev->comp); } else { - addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); + addr = vb2_dma_contig_plane_dma_addr( + &bcap_dev->cur_frm->vb.vb2_buf, 0); ppi->ops->update_addr(ppi, (unsigned long)addr); ppi->ops->start(ppi); } diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index fd7819d8922d..654e964f84a2 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -25,7 +25,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-fh.h> #include <media/v4l2-mem2mem.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include <media/videobuf2-vmalloc.h> @@ -179,31 +179,32 @@ static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx) } static int coda_bitstream_queue(struct coda_ctx *ctx, - struct vb2_buffer *src_buf) + struct vb2_v4l2_buffer *src_buf) { - u32 src_size = vb2_get_plane_payload(src_buf, 0); + u32 src_size = vb2_get_plane_payload(&src_buf->vb2_buf, 0); u32 n; - n = kfifo_in(&ctx->bitstream_fifo, vb2_plane_vaddr(src_buf, 0), - src_size); + n = kfifo_in(&ctx->bitstream_fifo, + vb2_plane_vaddr(&src_buf->vb2_buf, 0), src_size); if (n < src_size) return -ENOSPC; - src_buf->v4l2_buf.sequence = ctx->qsequence++; + src_buf->sequence = ctx->qsequence++; return 0; } static bool coda_bitstream_try_queue(struct coda_ctx *ctx, - struct vb2_buffer *src_buf) + struct vb2_v4l2_buffer *src_buf) { int ret; if (coda_get_bitstream_payload(ctx) + - vb2_get_plane_payload(src_buf, 0) + 512 >= ctx->bitstream.size) + vb2_get_plane_payload(&src_buf->vb2_buf, 0) + 512 >= + ctx->bitstream.size) return false; - if (vb2_plane_vaddr(src_buf, 0) == NULL) { + if (vb2_plane_vaddr(&src_buf->vb2_buf, 0) == NULL) { v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty buffer\n"); return true; } @@ -224,7 +225,7 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx, void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming) { - struct vb2_buffer *src_buf; + struct vb2_v4l2_buffer *src_buf; struct coda_buffer_meta *meta; unsigned long flags; u32 start; @@ -257,7 +258,7 @@ void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming) } /* Dump empty buffers */ - if (!vb2_get_plane_payload(src_buf, 0)) { + if (!vb2_get_plane_payload(&src_buf->vb2_buf, 0)) { src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); continue; @@ -276,9 +277,9 @@ void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming) meta = kmalloc(sizeof(*meta), GFP_KERNEL); if (meta) { - meta->sequence = src_buf->v4l2_buf.sequence; - meta->timecode = src_buf->v4l2_buf.timecode; - meta->timestamp = src_buf->v4l2_buf.timestamp; + meta->sequence = src_buf->sequence; + meta->timecode = src_buf->timecode; + meta->timestamp = src_buf->timestamp; meta->start = start; meta->end = ctx->bitstream_fifo.kfifo.in & ctx->bitstream_fifo.kfifo.mask; @@ -483,20 +484,21 @@ err: return ret; } -static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, +static int coda_encode_header(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, int header_code, u8 *header, int *size) { + struct vb2_buffer *vb = &buf->vb2_buf; struct coda_dev *dev = ctx->dev; size_t bufsize; int ret; int i; if (dev->devtype->product == CODA_960) - memset(vb2_plane_vaddr(buf, 0), 0, 64); + memset(vb2_plane_vaddr(vb, 0), 0, 64); - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), + coda_write(dev, vb2_dma_contig_plane_dma_addr(vb, 0), CODA_CMD_ENC_HEADER_BB_START); - bufsize = vb2_plane_size(buf, 0); + bufsize = vb2_plane_size(vb, 0); if (dev->devtype->product == CODA_960) bufsize /= 1024; coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE); @@ -509,14 +511,14 @@ static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, if (dev->devtype->product == CODA_960) { for (i = 63; i > 0; i--) - if (((char *)vb2_plane_vaddr(buf, 0))[i] != 0) + if (((char *)vb2_plane_vaddr(vb, 0))[i] != 0) break; *size = i + 1; } else { *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); } - memcpy(header, vb2_plane_vaddr(buf, 0), *size); + memcpy(header, vb2_plane_vaddr(vb, 0), *size); return 0; } @@ -799,7 +801,7 @@ static int coda_start_encoding(struct coda_ctx *ctx) struct v4l2_device *v4l2_dev = &dev->v4l2_dev; struct coda_q_data *q_data_src, *q_data_dst; u32 bitstream_buf, bitstream_size; - struct vb2_buffer *buf; + struct vb2_v4l2_buffer *buf; int gamma, ret, value; u32 dst_fourcc; int num_fb; @@ -810,7 +812,7 @@ static int coda_start_encoding(struct coda_ctx *ctx) dst_fourcc = q_data_dst->fourcc; buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); - bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); + bitstream_buf = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0); bitstream_size = q_data_dst->sizeimage; if (!coda_is_initialized(dev)) { @@ -1185,7 +1187,7 @@ out: static int coda_prepare_encode(struct coda_ctx *ctx) { struct coda_q_data *q_data_src, *q_data_dst; - struct vb2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; struct coda_dev *dev = ctx->dev; int force_ipicture; int quant_param = 0; @@ -1200,8 +1202,8 @@ static int coda_prepare_encode(struct coda_ctx *ctx) q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); dst_fourcc = q_data_dst->fourcc; - src_buf->v4l2_buf.sequence = ctx->osequence; - dst_buf->v4l2_buf.sequence = ctx->osequence; + src_buf->sequence = ctx->osequence; + dst_buf->sequence = ctx->osequence; ctx->osequence++; /* @@ -1209,12 +1211,12 @@ static int coda_prepare_encode(struct coda_ctx *ctx) * frame as IDR. This is a problem for some decoders that can't * recover when a frame is lost. */ - if (src_buf->v4l2_buf.sequence % ctx->params.gop_size) { - src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; - src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; + if (src_buf->sequence % ctx->params.gop_size) { + src_buf->flags |= V4L2_BUF_FLAG_PFRAME; + src_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME; } else { - src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; - src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; + src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; + src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME; } if (dev->devtype->product == CODA_960) @@ -1224,9 +1226,9 @@ static int coda_prepare_encode(struct coda_ctx *ctx) * Copy headers at the beginning of the first frame for H.264 only. * In MPEG4 they are already copied by the coda. */ - if (src_buf->v4l2_buf.sequence == 0) { + if (src_buf->sequence == 0) { pic_stream_buffer_addr = - vb2_dma_contig_plane_dma_addr(dst_buf, 0) + + vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0) + ctx->vpu_header_size[0] + ctx->vpu_header_size[1] + ctx->vpu_header_size[2]; @@ -1234,20 +1236,21 @@ static int coda_prepare_encode(struct coda_ctx *ctx) ctx->vpu_header_size[0] - ctx->vpu_header_size[1] - ctx->vpu_header_size[2]; - memcpy(vb2_plane_vaddr(dst_buf, 0), + memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0), &ctx->vpu_header[0][0], ctx->vpu_header_size[0]); - memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx->vpu_header_size[0], - &ctx->vpu_header[1][0], ctx->vpu_header_size[1]); - memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx->vpu_header_size[0] + - ctx->vpu_header_size[1], &ctx->vpu_header[2][0], - ctx->vpu_header_size[2]); + memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) + + ctx->vpu_header_size[0], &ctx->vpu_header[1][0], + ctx->vpu_header_size[1]); + memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) + + ctx->vpu_header_size[0] + ctx->vpu_header_size[1], + &ctx->vpu_header[2][0], ctx->vpu_header_size[2]); } else { pic_stream_buffer_addr = - vb2_dma_contig_plane_dma_addr(dst_buf, 0); + vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); pic_stream_buffer_size = q_data_dst->sizeimage; } - if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) { + if (src_buf->flags & V4L2_BUF_FLAG_KEYFRAME) { force_ipicture = 1; switch (dst_fourcc) { case V4L2_PIX_FMT_H264: @@ -1324,7 +1327,7 @@ static int coda_prepare_encode(struct coda_ctx *ctx) static void coda_finish_encode(struct coda_ctx *ctx) { - struct vb2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; struct coda_dev *dev = ctx->dev; u32 wr_ptr, start_ptr; @@ -1338,13 +1341,13 @@ static void coda_finish_encode(struct coda_ctx *ctx) wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); /* Calculate bytesused field */ - if (dst_buf->v4l2_buf.sequence == 0) { - vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr + + if (dst_buf->sequence == 0) { + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, ctx->vpu_header_size[0] + ctx->vpu_header_size[1] + ctx->vpu_header_size[2]); } else { - vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr); + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr); } v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n", @@ -1354,18 +1357,18 @@ static void coda_finish_encode(struct coda_ctx *ctx) coda_read(dev, CODA_RET_ENC_PIC_FLAG); if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0) { - dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; - dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; + dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; + dst_buf->flags &= ~V4L2_BUF_FLAG_PFRAME; } else { - dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; - dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; + dst_buf->flags |= V4L2_BUF_FLAG_PFRAME; + dst_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME; } - dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp; - dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_buf->v4l2_buf.flags |= - src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode; + dst_buf->timestamp = src_buf->timestamp; + dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_buf->flags |= + src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_buf->timecode = src_buf->timecode; v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); @@ -1378,8 +1381,8 @@ static void coda_finish_encode(struct coda_ctx *ctx) v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "job finished: encoding frame (%d) (%s)\n", - dst_buf->v4l2_buf.sequence, - (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? + dst_buf->sequence, + (dst_buf->flags & V4L2_BUF_FLAG_KEYFRAME) ? "KEYFRAME" : "PFRAME"); } @@ -1716,7 +1719,7 @@ static int coda_start_decoding(struct coda_ctx *ctx) static int coda_prepare_decode(struct coda_ctx *ctx) { - struct vb2_buffer *dst_buf; + struct vb2_v4l2_buffer *dst_buf; struct coda_dev *dev = ctx->dev; struct coda_q_data *q_data_dst; struct coda_buffer_meta *meta; @@ -1763,7 +1766,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx) * well as the rotator buffer output. * ROT_INDEX needs to be < 0x40, but > ctx->num_internal_frames. */ - coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->v4l2_buf.index, + coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->vb2_buf.index, CODA9_CMD_DEC_PIC_ROT_INDEX); reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y; @@ -1838,7 +1841,7 @@ static void coda_finish_decode(struct coda_ctx *ctx) struct coda_dev *dev = ctx->dev; struct coda_q_data *q_data_src; struct coda_q_data *q_data_dst; - struct vb2_buffer *dst_buf; + struct vb2_v4l2_buffer *dst_buf; struct coda_buffer_meta *meta; unsigned long payload; unsigned long flags; @@ -2029,15 +2032,15 @@ static void coda_finish_decode(struct coda_ctx *ctx) if (ctx->display_idx >= 0 && ctx->display_idx < ctx->num_internal_frames) { dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - dst_buf->v4l2_buf.sequence = ctx->osequence++; + dst_buf->sequence = ctx->osequence++; - dst_buf->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | + dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME); - dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx->display_idx]; + dst_buf->flags |= ctx->frame_types[ctx->display_idx]; meta = &ctx->frame_metas[ctx->display_idx]; - dst_buf->v4l2_buf.timecode = meta->timecode; - dst_buf->v4l2_buf.timestamp = meta->timestamp; + dst_buf->timecode = meta->timecode; + dst_buf->timestamp = meta->timestamp; trace_coda_dec_rot_done(ctx, dst_buf, meta); @@ -2052,15 +2055,15 @@ static void coda_finish_decode(struct coda_ctx *ctx) payload = width * height * 2; break; } - vb2_set_plane_payload(dst_buf, 0, payload); + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload); coda_m2m_buf_done(ctx, dst_buf, ctx->frame_errors[display_idx] ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "job finished: decoding frame (%d) (%s)\n", - dst_buf->v4l2_buf.sequence, - (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? + dst_buf->sequence, + (dst_buf->flags & V4L2_BUF_FLAG_KEYFRAME) ? "KEYFRAME" : "PFRAME"); } else { v4l2_dbg(1, coda_debug, &dev->v4l2_dev, diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index a4654e0c104d..15516a6e3a39 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -36,7 +36,7 @@ #include <media/v4l2-event.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-mem2mem.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include <media/videobuf2-vmalloc.h> @@ -84,9 +84,9 @@ unsigned int coda_read(struct coda_dev *dev, u32 reg) } void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data, - struct vb2_buffer *buf, unsigned int reg_y) + struct vb2_v4l2_buffer *buf, unsigned int reg_y) { - u32 base_y = vb2_dma_contig_plane_dma_addr(buf, 0); + u32 base_y = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0); u32 base_cb, base_cr; switch (q_data->fourcc) { @@ -684,17 +684,17 @@ static int coda_qbuf(struct file *file, void *priv, } static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx, - struct vb2_buffer *buf) + struct vb2_v4l2_buffer *buf) { struct vb2_queue *src_vq; src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); return ((ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) && - (buf->v4l2_buf.sequence == (ctx->qsequence - 1))); + (buf->sequence == (ctx->qsequence - 1))); } -void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_buffer *buf, +void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state) { const struct v4l2_event eos_event = { @@ -702,7 +702,7 @@ void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_buffer *buf, }; if (coda_buf_is_end_of_stream(ctx, buf)) { - buf->v4l2_buf.flags |= V4L2_BUF_FLAG_LAST; + buf->flags |= V4L2_BUF_FLAG_LAST; v4l2_event_queue_fh(&ctx->fh, &eos_event); } @@ -1131,8 +1131,7 @@ static void set_default_params(struct coda_ctx *ctx) /* * Queue operations */ -static int coda_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, +static int coda_queue_setup(struct vb2_queue *vq, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -1175,6 +1174,7 @@ static int coda_buf_prepare(struct vb2_buffer *vb) static void coda_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct vb2_queue *vq = vb->vb2_queue; struct coda_q_data *q_data; @@ -1193,12 +1193,12 @@ static void coda_buf_queue(struct vb2_buffer *vb) if (vb2_get_plane_payload(vb, 0) == 0) coda_bit_stream_end_flag(ctx); mutex_lock(&ctx->bitstream_mutex); - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); if (vb2_is_streaming(vb->vb2_queue)) coda_fill_bitstream(ctx, true); mutex_unlock(&ctx->bitstream_mutex); } else { - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } } @@ -1247,7 +1247,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) struct coda_ctx *ctx = vb2_get_drv_priv(q); struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev; struct coda_q_data *q_data_src, *q_data_dst; - struct vb2_buffer *buf; + struct vb2_v4l2_buffer *buf; int ret = 0; q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); @@ -1338,7 +1338,7 @@ static void coda_stop_streaming(struct vb2_queue *q) { struct coda_ctx *ctx = vb2_get_drv_priv(q); struct coda_dev *dev = ctx->dev; - struct vb2_buffer *buf; + struct vb2_v4l2_buffer *buf; unsigned long flags; bool stop; diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c index 11e734bc2cbd..96cd42a0baaf 100644 --- a/drivers/media/platform/coda/coda-jpeg.c +++ b/drivers/media/platform/coda/coda-jpeg.c @@ -178,12 +178,12 @@ int coda_jpeg_write_tables(struct coda_ctx *ctx) return 0; } -bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb) +bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_v4l2_buffer *vb) { - void *vaddr = vb2_plane_vaddr(vb, 0); + 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, 0) - 2)); + vb2_get_plane_payload(&vb->vb2_buf, 0) - 2)); return soi == SOI_MARKER && eoi == EOI_MARKER; } diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h index 59b2af9c7749..96532b06bd9e 100644 --- a/drivers/media/platform/coda/coda.h +++ b/drivers/media/platform/coda/coda.h @@ -24,7 +24,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fh.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include "coda_regs.h" @@ -243,7 +243,7 @@ extern int coda_debug; void coda_write(struct coda_dev *dev, u32 data, u32 reg); unsigned int coda_read(struct coda_dev *dev, u32 reg); void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data, - struct vb2_buffer *buf, unsigned int reg_y); + struct vb2_v4l2_buffer *buf, unsigned int reg_y); int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf, size_t size, const char *name, struct dentry *parent); @@ -284,12 +284,12 @@ static inline unsigned int coda_get_bitstream_payload(struct coda_ctx *ctx) void coda_bit_stream_end_flag(struct coda_ctx *ctx); -void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_buffer *buf, +void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state); int coda_h264_padding(int size, char *p); -bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb); +bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_v4l2_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/coda/trace.h b/drivers/media/platform/coda/trace.h index d9099a0f7c32..f20666a4aa89 100644 --- a/drivers/media/platform/coda/trace.h +++ b/drivers/media/platform/coda/trace.h @@ -5,7 +5,7 @@ #define __CODA_TRACE_H__ #include <linux/tracepoint.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include "coda.h" @@ -49,7 +49,7 @@ TRACE_EVENT(coda_bit_done, ); DECLARE_EVENT_CLASS(coda_buf_class, - TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf), + TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), TP_ARGS(ctx, buf), @@ -61,7 +61,7 @@ DECLARE_EVENT_CLASS(coda_buf_class, TP_fast_assign( __entry->minor = ctx->fh.vdev->minor; - __entry->index = buf->v4l2_buf.index; + __entry->index = buf->vb2_buf.index; __entry->ctx = ctx->idx; ), @@ -70,17 +70,17 @@ DECLARE_EVENT_CLASS(coda_buf_class, ); DEFINE_EVENT(coda_buf_class, coda_enc_pic_run, - TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf), + TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), TP_ARGS(ctx, buf) ); DEFINE_EVENT(coda_buf_class, coda_enc_pic_done, - TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf), + TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), TP_ARGS(ctx, buf) ); DECLARE_EVENT_CLASS(coda_buf_meta_class, - TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf, + TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, struct coda_buffer_meta *meta), TP_ARGS(ctx, buf, meta), @@ -95,7 +95,7 @@ DECLARE_EVENT_CLASS(coda_buf_meta_class, TP_fast_assign( __entry->minor = ctx->fh.vdev->minor; - __entry->index = buf->v4l2_buf.index; + __entry->index = buf->vb2_buf.index; __entry->start = meta->start; __entry->end = meta->end; __entry->ctx = ctx->idx; @@ -107,7 +107,7 @@ DECLARE_EVENT_CLASS(coda_buf_meta_class, ); DEFINE_EVENT(coda_buf_meta_class, coda_bit_queue, - TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf, + TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, struct coda_buffer_meta *meta), TP_ARGS(ctx, buf, meta) ); @@ -146,7 +146,7 @@ DEFINE_EVENT(coda_meta_class, coda_dec_pic_done, ); DEFINE_EVENT(coda_buf_meta_class, coda_dec_rot_done, - TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf, + TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, struct coda_buffer_meta *meta), TP_ARGS(ctx, buf, meta) ); diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index f69cdd7da10c..6d91422c4e4c 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -74,8 +74,8 @@ 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.v4l2_buf.timestamp); - vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&layer->cur_frm->vb.timestamp); + 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; } @@ -104,8 +104,8 @@ static void vpbe_isr_odd_field(struct vpbe_display *disp_obj, list_del(&layer->next_frm->list); spin_unlock(&disp_obj->dma_queue_lock); /* Mark state of the frame to active */ - layer->next_frm->vb.state = VB2_BUF_STATE_ACTIVE; - addr = vb2_dma_contig_plane_dma_addr(&layer->next_frm->vb, 0); + layer->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; + addr = vb2_dma_contig_plane_dma_addr(&layer->next_frm->vb.vb2_buf, 0); osd_device->ops.start_layer(osd_device, layer->layer_info.id, addr, @@ -228,11 +228,12 @@ 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 struct v4l2_format *fmt, +vpbe_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; /* 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; @@ -259,8 +260,9 @@ vpbe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, */ static void vpbe_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); /* Get the file handle object and layer object */ - struct vpbe_disp_buffer *buf = container_of(vb, + struct vpbe_disp_buffer *buf = container_of(vbuf, struct vpbe_disp_buffer, vb); struct vpbe_layer *layer = vb2_get_drv_priv(vb->vb2_queue); struct vpbe_display *disp = layer->disp_dev; @@ -290,7 +292,7 @@ static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count) /* Remove buffer from the buffer queue */ list_del(&layer->cur_frm->list); /* Mark state of the current frame to active */ - layer->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; + layer->cur_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; /* Initialize field_id and started member */ layer->field_id = 0; @@ -299,10 +301,12 @@ static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count) if (ret < 0) { struct vpbe_disp_buffer *buf, *tmp; - vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&layer->cur_frm->vb.vb2_buf, + VB2_BUF_STATE_QUEUED); list_for_each_entry_safe(buf, tmp, &layer->dma_queue, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_QUEUED); } return ret; @@ -332,13 +336,14 @@ static void vpbe_stop_streaming(struct vb2_queue *vq) /* release all active buffers */ spin_lock_irqsave(&disp->dma_queue_lock, flags); if (layer->cur_frm == layer->next_frm) { - vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&layer->cur_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); } else { if (layer->cur_frm != NULL) - vb2_buffer_done(&layer->cur_frm->vb, + vb2_buffer_done(&layer->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); if (layer->next_frm != NULL) - vb2_buffer_done(&layer->next_frm->vb, + vb2_buffer_done(&layer->next_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); } @@ -346,7 +351,8 @@ static void vpbe_stop_streaming(struct vb2_queue *vq) layer->next_frm = list_entry(layer->dma_queue.next, struct vpbe_disp_buffer, list); list_del(&layer->next_frm->list); - vb2_buffer_done(&layer->next_frm->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&layer->next_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&disp->dma_queue_lock, flags); } @@ -383,7 +389,7 @@ static int vpbe_set_osd_display_params(struct vpbe_display *disp_dev, unsigned long addr; int ret; - addr = vb2_dma_contig_plane_dma_addr(&layer->cur_frm->vb, 0); + addr = vb2_dma_contig_plane_dma_addr(&layer->cur_frm->vb.vb2_buf, 0); /* Set address in the display registers */ osd_device->ops.start_layer(osd_device, layer->layer_info.id, diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index a5f548138b91..c1e573b7cc6f 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -57,7 +57,8 @@ static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = { {1, 1} }; /* Is set to 1 in case of SDTV formats, 2 in case of HDTV formats. */ static int ycmux_mode; -static inline struct vpif_cap_buffer *to_vpif_buffer(struct vb2_buffer *vb) +static inline +struct vpif_cap_buffer *to_vpif_buffer(struct vb2_v4l2_buffer *vb) { return container_of(vb, struct vpif_cap_buffer, vb); } @@ -72,6 +73,7 @@ static inline struct vpif_cap_buffer *to_vpif_buffer(struct vb2_buffer *vb) */ static int vpif_buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *q = vb->vb2_queue; struct channel_obj *ch = vb2_get_drv_priv(q); struct common_obj *common; @@ -85,7 +87,7 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb) if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) return -EINVAL; - vb->v4l2_buf.field = common->fmt.fmt.pix.field; + vbuf->field = common->fmt.fmt.pix.field; addr = vb2_dma_contig_plane_dma_addr(vb, 0); if (!IS_ALIGNED((addr + common->ytop_off), 8) || @@ -112,10 +114,11 @@ 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 struct v4l2_format *fmt, + 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; @@ -145,8 +148,9 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq, */ static void vpif_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue); - struct vpif_cap_buffer *buf = to_vpif_buffer(vb); + struct vpif_cap_buffer *buf = to_vpif_buffer(vbuf); struct common_obj *common; unsigned long flags; @@ -214,7 +218,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) list_del(&common->cur_frm->list); spin_unlock_irqrestore(&common->irqlock, flags); - addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); + addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb.vb2_buf, 0); common->set_addr(addr + common->ytop_off, addr + common->ybtm_off, @@ -243,7 +247,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) err: list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); } spin_unlock_irqrestore(&common->irqlock, flags); @@ -286,13 +290,14 @@ static void vpif_stop_streaming(struct vb2_queue *vq) /* release all active buffers */ spin_lock_irqsave(&common->irqlock, flags); if (common->cur_frm == common->next_frm) { - vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&common->cur_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); } else { if (common->cur_frm != NULL) - vb2_buffer_done(&common->cur_frm->vb, + vb2_buffer_done(&common->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); if (common->next_frm != NULL) - vb2_buffer_done(&common->next_frm->vb, + vb2_buffer_done(&common->next_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); } @@ -300,7 +305,8 @@ static void vpif_stop_streaming(struct vb2_queue *vq) common->next_frm = list_entry(common->dma_queue.next, struct vpif_cap_buffer, list); list_del(&common->next_frm->list); - vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&common->next_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&common->irqlock, flags); } @@ -325,9 +331,8 @@ static struct vb2_ops video_qops = { */ static void vpif_process_buffer_complete(struct common_obj *common) { - v4l2_get_timestamp(&common->cur_frm->vb.v4l2_buf.timestamp); - vb2_buffer_done(&common->cur_frm->vb, - VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&common->cur_frm->vb.timestamp); + vb2_buffer_done(&common->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); /* Make curFrm pointing to nextFrm */ common->cur_frm = common->next_frm; } @@ -350,7 +355,7 @@ static void vpif_schedule_next_buffer(struct common_obj *common) /* Remove that buffer from the buffer queue */ list_del(&common->next_frm->list); spin_unlock(&common->irqlock); - addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0); + addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb.vb2_buf, 0); /* Set top and bottom field addresses in VPIF registers */ common->set_addr(addr + common->ytop_off, diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index 8b8a663f6b22..4a7600929b61 100644 --- a/drivers/media/platform/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h @@ -52,7 +52,7 @@ struct video_obj { }; struct vpif_cap_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 682e5d578bf7..fd2780306c17 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -53,7 +53,8 @@ static struct device *vpif_dev; static void vpif_calculate_offsets(struct channel_obj *ch); static void vpif_config_addr(struct channel_obj *ch, int muxmode); -static inline struct vpif_disp_buffer *to_vpif_buffer(struct vb2_buffer *vb) +static inline +struct vpif_disp_buffer *to_vpif_buffer(struct vb2_v4l2_buffer *vb) { return container_of(vb, struct vpif_disp_buffer, vb); } @@ -68,6 +69,7 @@ static inline struct vpif_disp_buffer *to_vpif_buffer(struct vb2_buffer *vb) */ static int vpif_buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue); struct common_obj *common; @@ -77,7 +79,7 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb) if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) return -EINVAL; - vb->v4l2_buf.field = common->fmt.fmt.pix.field; + vbuf->field = common->fmt.fmt.pix.field; if (vb->vb2_queue->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { unsigned long addr = vb2_dma_contig_plane_dma_addr(vb, 0); @@ -107,10 +109,11 @@ 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 struct v4l2_format *fmt, + 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]; @@ -138,7 +141,8 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq, */ static void vpif_buffer_queue(struct vb2_buffer *vb) { - struct vpif_disp_buffer *buf = to_vpif_buffer(vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct vpif_disp_buffer *buf = to_vpif_buffer(vbuf); struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue); struct common_obj *common; unsigned long flags; @@ -197,7 +201,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) list_del(&common->cur_frm->list); spin_unlock_irqrestore(&common->irqlock, flags); - addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); + addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb.vb2_buf, 0); common->set_addr((addr + common->ytop_off), (addr + common->ybtm_off), (addr + common->ctop_off), @@ -229,7 +233,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) err: list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); } spin_unlock_irqrestore(&common->irqlock, flags); @@ -264,13 +268,14 @@ static void vpif_stop_streaming(struct vb2_queue *vq) /* release all active buffers */ spin_lock_irqsave(&common->irqlock, flags); if (common->cur_frm == common->next_frm) { - vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&common->cur_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); } else { if (common->cur_frm != NULL) - vb2_buffer_done(&common->cur_frm->vb, + vb2_buffer_done(&common->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); if (common->next_frm != NULL) - vb2_buffer_done(&common->next_frm->vb, + vb2_buffer_done(&common->next_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); } @@ -278,7 +283,8 @@ static void vpif_stop_streaming(struct vb2_queue *vq) common->next_frm = list_entry(common->dma_queue.next, struct vpif_disp_buffer, list); list_del(&common->next_frm->list); - vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&common->next_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&common->irqlock, flags); } @@ -306,7 +312,7 @@ static void process_progressive_mode(struct common_obj *common) spin_unlock(&common->irqlock); /* Set top and bottom field addrs in VPIF registers */ - addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0); + addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb.vb2_buf, 0); common->set_addr(addr + common->ytop_off, addr + common->ybtm_off, addr + common->ctop_off, @@ -324,10 +330,10 @@ 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.v4l2_buf.timestamp); + v4l2_get_timestamp(&common->cur_frm->vb.timestamp); /* Change status of the cur_frm */ - vb2_buffer_done(&common->cur_frm->vb, - VB2_BUF_STATE_DONE); + vb2_buffer_done(&common->cur_frm->vb.vb2_buf, + VB2_BUF_STATE_DONE); /* Make cur_frm pointing to next_frm */ common->cur_frm = common->next_frm; @@ -380,10 +386,10 @@ 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. - v4l2_buf.timestamp); - vb2_buffer_done(&common->cur_frm->vb, - VB2_BUF_STATE_DONE); + v4l2_get_timestamp( + &common->cur_frm->vb.timestamp); + vb2_buffer_done(&common->cur_frm->vb.vb2_buf, + VB2_BUF_STATE_DONE); /* Make cur_frm pointing to next_frm */ common->cur_frm = common->next_frm; } diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h index 849e0e385f18..e7a1723a1b7a 100644 --- a/drivers/media/platform/davinci/vpif_display.h +++ b/drivers/media/platform/davinci/vpif_display.h @@ -62,7 +62,7 @@ struct video_obj { }; struct vpif_disp_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h index fa572aacdb3f..e93a2336cfa2 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.h +++ b/drivers/media/platform/exynos-gsc/gsc-core.h @@ -19,7 +19,7 @@ #include <linux/videodev2.h> #include <linux/io.h> #include <linux/pm_runtime.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-mem2mem.h> @@ -136,7 +136,7 @@ struct gsc_fmt { * @idx : index of G-Scaler input buffer */ struct gsc_input_buf { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; int idx; }; diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index d5cffef2e227..d82e717acba7 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -77,7 +77,7 @@ static void gsc_m2m_stop_streaming(struct vb2_queue *q) void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state) { - struct vb2_buffer *src_vb, *dst_vb; + struct vb2_v4l2_buffer *src_vb, *dst_vb; if (!ctx || !ctx->m2m_ctx) return; @@ -86,11 +86,11 @@ 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->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp; - dst_vb->v4l2_buf.timecode = src_vb->v4l2_buf.timecode; - dst_vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_vb->v4l2_buf.flags |= - src_vb->v4l2_buf.flags + dst_vb->timestamp = src_vb->timestamp; + dst_vb->timecode = src_vb->timecode; + dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_vb->flags |= + src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; v4l2_m2m_buf_done(src_vb, vb_state); @@ -109,23 +109,23 @@ static void gsc_m2m_job_abort(void *priv) static int gsc_get_bufs(struct gsc_ctx *ctx) { struct gsc_frame *s_frame, *d_frame; - struct vb2_buffer *src_vb, *dst_vb; + struct vb2_v4l2_buffer *src_vb, *dst_vb; int ret; s_frame = &ctx->s_frame; d_frame = &ctx->d_frame; src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); - ret = gsc_prepare_addr(ctx, src_vb, s_frame, &s_frame->addr); + ret = gsc_prepare_addr(ctx, &src_vb->vb2_buf, s_frame, &s_frame->addr); if (ret) return ret; dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); - ret = gsc_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr); + ret = gsc_prepare_addr(ctx, &dst_vb->vb2_buf, d_frame, &d_frame->addr); if (ret) return ret; - dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp; + dst_vb->timestamp = src_vb->timestamp; return 0; } @@ -212,7 +212,7 @@ put_device: } static int gsc_m2m_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *allocators[]) { @@ -255,12 +255,13 @@ static int gsc_m2m_buf_prepare(struct vb2_buffer *vb) static void gsc_m2m_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); pr_debug("ctx: %p, ctx->state: 0x%x", ctx, ctx->state); if (ctx->m2m_ctx) - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf); } static struct vb2_ops gsc_m2m_qops = { diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index cfebf292e15a..99e57320e6f7 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -24,7 +24,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-mem2mem.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "common.h" @@ -103,7 +103,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) /* Release unused buffers */ while (!suspend && !list_empty(&cap->pending_buf_q)) { buf = fimc_pending_queue_pop(cap); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } /* If suspending put unused buffers onto pending queue */ while (!list_empty(&cap->active_buf_q)) { @@ -111,7 +111,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) if (suspend) fimc_pending_queue_add(cap, buf); else - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } fimc_hw_reset(fimc); @@ -183,8 +183,6 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) struct v4l2_subdev *csis = p->subdevs[IDX_CSIS]; struct fimc_frame *f = &cap->ctx->d_frame; struct fimc_vid_buffer *v_buf; - struct timeval *tv; - struct timespec ts; if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) { wake_up(&fimc->irq_queue); @@ -193,16 +191,12 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) if (!list_empty(&cap->active_buf_q) && test_bit(ST_CAPT_RUN, &fimc->state) && deq_buf) { - ktime_get_real_ts(&ts); - v_buf = fimc_active_queue_pop(cap); - tv = &v_buf->vb.v4l2_buf.timestamp; - tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC; - v_buf->vb.v4l2_buf.sequence = cap->frame_count++; + v4l2_get_timestamp(&v_buf->vb.timestamp); + v_buf->vb.sequence = cap->frame_count++; - vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&v_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } if (!list_empty(&cap->pending_buf_q)) { @@ -233,7 +227,7 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) list_for_each_entry(v_buf, &cap->active_buf_q, list) { if (v_buf->index != index) continue; - vaddr = vb2_plane_vaddr(&v_buf->vb, plane); + vaddr = vb2_plane_vaddr(&v_buf->vb.vb2_buf, plane); v4l2_subdev_call(csis, video, s_rx_buffer, vaddr, &size); break; @@ -338,16 +332,17 @@ int fimc_capture_resume(struct fimc_dev *fimc) if (list_empty(&vid_cap->pending_buf_q)) break; buf = fimc_pending_queue_pop(vid_cap); - buffer_queue(&buf->vb); + buffer_queue(&buf->vb.vb2_buf); } return 0; } -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt, +static int 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; const struct v4l2_pix_format_mplane *pixm = NULL; struct fimc_ctx *ctx = vq->drv_priv; struct fimc_frame *frame = &ctx->d_frame; @@ -410,8 +405,9 @@ static int buffer_prepare(struct vb2_buffer *vb) static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct fimc_vid_buffer *buf - = container_of(vb, struct fimc_vid_buffer, vb); + = container_of(vbuf, struct fimc_vid_buffer, vb); struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct fimc_dev *fimc = ctx->fimc_dev; struct fimc_vid_cap *vid_cap = &fimc->vid_cap; @@ -420,7 +416,7 @@ static void buffer_queue(struct vb2_buffer *vb) int min_bufs; spin_lock_irqsave(&fimc->slock, flags); - fimc_prepare_addr(ctx, &buf->vb, &ctx->d_frame, &buf->paddr); + fimc_prepare_addr(ctx, &buf->vb.vb2_buf, &ctx->d_frame, &buf->paddr); if (!test_bit(ST_CAPT_SUSPENDED, &fimc->state) && !test_bit(ST_CAPT_STREAM, &fimc->state) && @@ -1472,7 +1468,8 @@ void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification, if (!list_empty(&fimc->vid_cap.active_buf_q)) { buf = list_entry(fimc->vid_cap.active_buf_q.next, struct fimc_vid_buffer, list); - vb2_set_plane_payload(&buf->vb, 0, *((u32 *)arg)); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, + *((u32 *)arg)); } fimc_capture_irq_handler(fimc, 1); fimc_deactivate_capture(fimc); diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index 1101c41ac117..cef2a7f07cdb 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c @@ -27,7 +27,7 @@ #include <linux/slab.h> #include <linux/clk.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "fimc-core.h" diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h index 7328f0845065..d336fa2916df 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ b/drivers/media/platform/exynos4-is/fimc-core.h @@ -22,7 +22,7 @@ #include <linux/sizes.h> #include <media/media-entity.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-mem2mem.h> @@ -224,7 +224,7 @@ struct fimc_addr { * @index: buffer index for the output DMA engine */ struct fimc_vid_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; struct fimc_addr paddr; int index; diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h index e0be691af2d3..386eb49ece7e 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.h +++ b/drivers/media/platform/exynos4-is/fimc-is.h @@ -22,7 +22,7 @@ #include <linux/sizes.h> #include <linux/spinlock.h> #include <linux/types.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/v4l2-ctrls.h> #include "fimc-isp.h" diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index 76b6b4d14616..6e6648446f00 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c @@ -28,7 +28,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include <media/exynos-fimc.h> @@ -39,10 +39,11 @@ #include "fimc-is-param.h" static int isp_video_capture_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *pfmt, + 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; @@ -194,10 +195,11 @@ static int isp_video_capture_buffer_prepare(struct vb2_buffer *vb) static void isp_video_capture_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue); struct fimc_is_video *video = &isp->video_capture; struct fimc_is *is = fimc_isp_to_is(isp); - struct isp_video_buf *ivb = to_isp_video_buf(vb); + struct isp_video_buf *ivb = to_isp_video_buf(vbuf); unsigned long flags; unsigned int i; @@ -220,7 +222,7 @@ static void isp_video_capture_buffer_queue(struct vb2_buffer *vb) isp_dbg(2, &video->ve.vdev, "dma_buf %pad (%d/%d/%d) addr: %pad\n", - &buf_index, ivb->index, i, vb->v4l2_buf.index, + &buf_index, ivb->index, i, vb->index, &ivb->dma_addr[i]); } @@ -242,7 +244,7 @@ static void isp_video_capture_buffer_queue(struct vb2_buffer *vb) void fimc_isp_video_irq_handler(struct fimc_is *is) { struct fimc_is_video *video = &is->isp.video_capture; - struct vb2_buffer *vb; + struct vb2_v4l2_buffer *vbuf; int buf_index; /* TODO: Ensure the DMA is really stopped in stop_streaming callback */ @@ -250,10 +252,10 @@ void fimc_isp_video_irq_handler(struct fimc_is *is) return; buf_index = (is->i2h_cmd.args[1] - 1) % video->buf_count; - vb = &video->buffers[buf_index]->vb; + vbuf = &video->buffers[buf_index]->vb; - v4l2_get_timestamp(&vb->v4l2_buf.timestamp); - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&vbuf->timestamp); + vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); video->buf_mask &= ~BIT(buf_index); fimc_is_hw_set_isp_buf_mask(is, video->buf_mask); diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.h b/drivers/media/platform/exynos4-is/fimc-isp-video.h index 98c662654bb6..f79a1b348aa6 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.h +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.h @@ -11,7 +11,7 @@ #ifndef FIMC_ISP_VIDEO__ #define FIMC_ISP_VIDEO__ -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include "fimc-isp.h" #ifdef CONFIG_VIDEO_EXYNOS4_ISP_DMA_CAPTURE diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h index b99be09b49fc..c2d25df85db9 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.h +++ b/drivers/media/platform/exynos4-is/fimc-isp.h @@ -21,7 +21,7 @@ #include <linux/videodev2.h> #include <media/media-entity.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/v4l2-device.h> #include <media/v4l2-mediabus.h> #include <media/exynos-fimc.h> @@ -102,7 +102,7 @@ struct fimc_isp_ctrls { }; struct isp_video_buf { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; dma_addr_t dma_addr[FIMC_ISP_MAX_PLANES]; unsigned int index; }; diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index ca6261a86a5f..60660c3a5de0 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -28,7 +28,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-mem2mem.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include <media/exynos-fimc.h> @@ -200,7 +200,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend) /* Release unused buffers */ while (!suspend && !list_empty(&fimc->pending_buf_q)) { buf = fimc_lite_pending_queue_pop(fimc); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } /* If suspending put unused buffers onto pending queue */ while (!list_empty(&fimc->active_buf_q)) { @@ -208,7 +208,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend) if (suspend) fimc_lite_pending_queue_add(fimc, buf); else - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&fimc->slock, flags); @@ -254,8 +254,6 @@ static irqreturn_t flite_irq_handler(int irq, void *priv) struct fimc_lite *fimc = priv; struct flite_buffer *vbuf; unsigned long flags; - struct timeval *tv; - struct timespec ts; u32 intsrc; spin_lock_irqsave(&fimc->slock, flags); @@ -294,13 +292,10 @@ 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); - ktime_get_ts(&ts); - tv = &vbuf->vb.v4l2_buf.timestamp; - tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC; - vbuf->vb.v4l2_buf.sequence = fimc->frame_count++; + v4l2_get_timestamp(&vbuf->vb.timestamp); + vbuf->vb.sequence = fimc->frame_count++; flite_hw_mask_dma_buffer(fimc, vbuf->index); - vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); } if (test_bit(ST_FLITE_CONFIG, &fimc->state)) @@ -360,10 +355,11 @@ static void stop_streaming(struct vb2_queue *q) fimc_lite_stop_capture(fimc, false); } -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt, +static int 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; const struct v4l2_pix_format_mplane *pixm = NULL; struct fimc_lite *fimc = vq->drv_priv; struct flite_frame *frame = &fimc->out_frame; @@ -422,8 +418,9 @@ static int buffer_prepare(struct vb2_buffer *vb) static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct flite_buffer *buf - = container_of(vb, struct flite_buffer, vb); + = container_of(vbuf, struct flite_buffer, vb); struct fimc_lite *fimc = vb2_get_drv_priv(vb->vb2_queue); unsigned long flags; @@ -1637,7 +1634,7 @@ static int fimc_lite_resume(struct device *dev) if (list_empty(&fimc->pending_buf_q)) break; buf = fimc_lite_pending_queue_pop(fimc); - buffer_queue(&buf->vb); + buffer_queue(&buf->vb.vb2_buf); } return 0; } diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h index ea19dc7be63e..b302305dedbe 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.h +++ b/drivers/media/platform/exynos4-is/fimc-lite.h @@ -19,7 +19,7 @@ #include <linux/videodev2.h> #include <media/media-entity.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-mediabus.h> @@ -100,7 +100,7 @@ struct flite_frame { * @index: DMA start address register's index */ struct flite_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; dma_addr_t paddr; unsigned short index; diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c index d2bfe7c2a6b4..4d1d64a46b21 100644 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c @@ -24,7 +24,7 @@ #include <linux/slab.h> #include <linux/clk.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "common.h" @@ -42,7 +42,7 @@ static unsigned int get_m2m_fmt_flags(unsigned int stream_type) void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state) { - struct vb2_buffer *src_vb, *dst_vb; + struct vb2_v4l2_buffer *src_vb, *dst_vb; if (!ctx || !ctx->fh.m2m_ctx) return; @@ -99,7 +99,7 @@ static void stop_streaming(struct vb2_queue *q) static void fimc_device_run(void *priv) { - struct vb2_buffer *src_vb, *dst_vb; + struct vb2_v4l2_buffer *src_vb, *dst_vb; struct fimc_ctx *ctx = priv; struct fimc_frame *sf, *df; struct fimc_dev *fimc; @@ -123,19 +123,19 @@ static void fimc_device_run(void *priv) } src_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - ret = fimc_prepare_addr(ctx, src_vb, sf, &sf->paddr); + ret = fimc_prepare_addr(ctx, &src_vb->vb2_buf, sf, &sf->paddr); if (ret) goto dma_unlock; dst_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); - ret = fimc_prepare_addr(ctx, dst_vb, df, &df->paddr); + ret = fimc_prepare_addr(ctx, &dst_vb->vb2_buf, df, &df->paddr); if (ret) goto dma_unlock; - dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp; - dst_vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_vb->v4l2_buf.flags |= - src_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_vb->timestamp = src_vb->timestamp; + dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_vb->flags |= + src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; /* Reconfigure hardware if the context has changed. */ if (fimc->m2m.ctx != ctx) { @@ -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 struct v4l2_format *fmt, +static int fimc_queue_setup(struct vb2_queue *vq, const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *allocators[]) { @@ -220,8 +220,9 @@ static int fimc_buf_prepare(struct vb2_buffer *vb) static void fimc_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } static struct vb2_ops fimc_qops = { diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index d74e1bec3d86..4b85105dc159 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -706,7 +706,8 @@ static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id) else offset = S5PCSIS_PKTDATA_ODD; - memcpy(pktbuf->data, state->regs + offset, pktbuf->len); + memcpy(pktbuf->data, (u8 __force *)state->regs + offset, + pktbuf->len); pktbuf->data = NULL; rmb(); } diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index c07f367aa436..29973f9bf8db 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -200,18 +200,18 @@ static void dma_callback(void *data) { struct deinterlace_ctx *curr_ctx = data; struct deinterlace_dev *pcdev = curr_ctx->dev; - struct vb2_buffer *src_vb, *dst_vb; + struct vb2_v4l2_buffer *src_vb, *dst_vb; atomic_set(&pcdev->busy, 0); src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); - dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp; - dst_vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_vb->v4l2_buf.flags |= - src_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_vb->v4l2_buf.timecode = src_vb->v4l2_buf.timecode; + dst_vb->timestamp = src_vb->timestamp; + dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_vb->flags |= + src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_vb->timecode = src_vb->timecode; v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); @@ -225,7 +225,7 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op, int do_callback) { struct deinterlace_q_data *s_q_data; - struct vb2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; struct deinterlace_dev *pcdev = ctx->dev; struct dma_chan *chan = pcdev->dma_chan; struct dma_device *dmadev = chan->device; @@ -243,8 +243,9 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op, s_height = s_q_data->height; s_size = s_width * s_height; - p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(src_buf, 0); - p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(dst_buf, 0); + p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, + 0); if (!p_in || !p_out) { v4l2_err(&pcdev->v4l2_dev, "Acquiring kernel pointers to buffers failed\n"); @@ -797,7 +798,7 @@ struct vb2_dc_conf { }; static int deinterlace_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -849,8 +850,10 @@ static int deinterlace_buf_prepare(struct vb2_buffer *vb) static void deinterlace_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); + + v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf); } static struct vb2_ops deinterlace_qops = { diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 5e2b4df48b3c..aa2b44041d3f 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -201,18 +201,18 @@ struct mcam_dma_desc { /* * Our buffer type for working with videobuf2. Note that the vb2 - * developers have decreed that struct vb2_buffer must be at the + * developers have decreed that struct vb2_v4l2_buffer must be at the * beginning of this structure. */ struct mcam_vb_buffer { - struct vb2_buffer vb_buf; + struct vb2_v4l2_buffer vb_buf; struct list_head queue; struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */ dma_addr_t dma_desc_pa; /* Descriptor physical address */ int dma_desc_nent; /* Number of mapped descriptors */ }; -static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb) +static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_v4l2_buffer *vb) { return container_of(vb, struct mcam_vb_buffer, vb_buf); } @@ -221,14 +221,14 @@ static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb) * Hand a completed buffer back to user space. */ static void mcam_buffer_done(struct mcam_camera *cam, int frame, - struct vb2_buffer *vbuf) + struct vb2_v4l2_buffer *vbuf) { - vbuf->v4l2_buf.bytesused = cam->pix_format.sizeimage; - vbuf->v4l2_buf.sequence = cam->buf_seq[frame]; - vbuf->v4l2_buf.field = V4L2_FIELD_NONE; - v4l2_get_timestamp(&vbuf->v4l2_buf.timestamp); - vb2_set_plane_payload(vbuf, 0, cam->pix_format.sizeimage); - vb2_buffer_done(vbuf, VB2_BUF_STATE_DONE); + 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); + vb2_set_plane_payload(&vbuf->vb2_buf, 0, cam->pix_format.sizeimage); + vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); } @@ -482,7 +482,8 @@ static void mcam_frame_tasklet(unsigned long data) * Drop the lock during the big copy. This *should* be safe... */ spin_unlock_irqrestore(&cam->dev_lock, flags); - memcpy(vb2_plane_vaddr(&buf->vb_buf, 0), cam->dma_bufs[bufno], + memcpy(vb2_plane_vaddr(&buf->vb_buf.vb2_buf, 0), + cam->dma_bufs[bufno], cam->pix_format.sizeimage); mcam_buffer_done(cam, bufno, &buf->vb_buf); spin_lock_irqsave(&cam->dev_lock, flags); @@ -548,7 +549,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame) { struct mcam_vb_buffer *buf; dma_addr_t dma_handle; - struct vb2_buffer *vb; + struct vb2_v4l2_buffer *vb; /* * If there are no available buffers, go into single mode @@ -570,7 +571,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame) cam->vb_bufs[frame] = buf; vb = &buf->vb_buf; - dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0); + dma_handle = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0); mcam_write_yuv_bases(cam, frame, dma_handle); } @@ -1048,10 +1049,11 @@ static int mcam_read_setup(struct mcam_camera *cam) */ static int mcam_vb_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, unsigned int *nbufs, + const void *parg, 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; @@ -1071,7 +1073,8 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq, static void mcam_vb_buf_queue(struct vb2_buffer *vb) { - struct mcam_vb_buffer *mvb = vb_to_mvb(vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf); struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); unsigned long flags; int start; @@ -1096,14 +1099,14 @@ static void mcam_vb_requeue_bufs(struct vb2_queue *vq, spin_lock_irqsave(&cam->dev_lock, flags); list_for_each_entry_safe(buf, node, &cam->buffers, queue) { - vb2_buffer_done(&buf->vb_buf, state); + vb2_buffer_done(&buf->vb_buf.vb2_buf, state); list_del(&buf->queue); } for (i = 0; i < MAX_DMA_BUFS; i++) { buf = cam->vb_bufs[i]; if (buf) { - vb2_buffer_done(&buf->vb_buf, state); + vb2_buffer_done(&buf->vb_buf.vb2_buf, state); cam->vb_bufs[i] = NULL; } } @@ -1198,7 +1201,8 @@ static const struct vb2_ops mcam_vb2_ops = { */ static int mcam_vb_sg_buf_init(struct vb2_buffer *vb) { - struct mcam_vb_buffer *mvb = vb_to_mvb(vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf); struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1; @@ -1214,7 +1218,8 @@ static int mcam_vb_sg_buf_init(struct vb2_buffer *vb) static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb) { - struct mcam_vb_buffer *mvb = vb_to_mvb(vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf); struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0); struct mcam_dma_desc *desc = mvb->dma_desc; struct scatterlist *sg; @@ -1230,8 +1235,9 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb) static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); - struct mcam_vb_buffer *mvb = vb_to_mvb(vb); + struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf); int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1; dma_free_coherent(cam->dev, ndesc * sizeof(struct mcam_dma_desc), diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h index 97167f6ffd1e..35cd9e5aedf8 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.h +++ b/drivers/media/platform/marvell-ccic/mcam-core.h @@ -10,7 +10,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-dev.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> /* * Create our own symbols for the supported buffer modes, but, for now, diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index 87314b743f55..03a1b606655d 100644 --- a/drivers/media/platform/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -351,7 +351,7 @@ static irqreturn_t emmaprp_irq(int irq_emma, void *data) { struct emmaprp_dev *pcdev = data; struct emmaprp_ctx *curr_ctx; - struct vb2_buffer *src_vb, *dst_vb; + struct vb2_v4l2_buffer *src_vb, *dst_vb; unsigned long flags; u32 irqst; @@ -375,13 +375,13 @@ 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->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp; - dst_vb->v4l2_buf.flags &= + dst_vb->timestamp = src_vb->timestamp; + dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_vb->v4l2_buf.flags |= - src_vb->v4l2_buf.flags + dst_vb->flags |= + src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_vb->v4l2_buf.timecode = src_vb->v4l2_buf.timecode; + dst_vb->timecode = src_vb->timecode; spin_lock_irqsave(&pcdev->irqlock, flags); v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); @@ -689,7 +689,7 @@ static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = { * Queue operations */ static int emmaprp_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -742,8 +742,9 @@ static int emmaprp_buf_prepare(struct vb2_buffer *vb) static void emmaprp_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf); } static struct vb2_ops emmaprp_qops = { diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c index 20434e83e801..94d4c295d3d0 100644 --- a/drivers/media/platform/omap3isp/ispstat.c +++ b/drivers/media/platform/omap3isp/ispstat.c @@ -235,7 +235,7 @@ static int isp_stat_buf_queue(struct ispstat *stat) if (!stat->active_buf) return STAT_NO_BUF; - ktime_get_ts(&stat->active_buf->ts); + v4l2_get_timestamp(&stat->active_buf->ts); stat->active_buf->buf_size = stat->buf_size; if (isp_stat_buf_check_magic(stat, stat->active_buf)) { @@ -496,8 +496,7 @@ int omap3isp_stat_request_statistics(struct ispstat *stat, return PTR_ERR(buf); } - data->ts.tv_sec = buf->ts.tv_sec; - data->ts.tv_usec = buf->ts.tv_nsec / NSEC_PER_USEC; + data->ts = buf->ts; data->config_counter = buf->config_counter; data->frame_number = buf->frame_number; data->buf_size = buf->buf_size; diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h index b79380d83fcf..6d9b0244f320 100644 --- a/drivers/media/platform/omap3isp/ispstat.h +++ b/drivers/media/platform/omap3isp/ispstat.h @@ -39,7 +39,7 @@ struct ispstat_buffer { struct sg_table sgt; void *virt_addr; dma_addr_t dma_addr; - struct timespec ts; + struct timeval ts; u32 buf_size; u32 frame_number; u16 config_counter; diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index 41bb8df91f72..f4f591652432 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -320,7 +320,7 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh) */ static int isp_video_queue_setup(struct vb2_queue *queue, - const struct v4l2_format *fmt, + const void *parg, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -342,8 +342,9 @@ static int isp_video_queue_setup(struct vb2_queue *queue, static int isp_video_buffer_prepare(struct vb2_buffer *buf) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(buf); struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue); - struct isp_buffer *buffer = to_isp_buffer(buf); + struct isp_buffer *buffer = to_isp_buffer(vbuf); struct isp_video *video = vfh->video; dma_addr_t addr; @@ -363,7 +364,8 @@ static int isp_video_buffer_prepare(struct vb2_buffer *buf) return -EINVAL; } - vb2_set_plane_payload(&buffer->vb, 0, vfh->format.fmt.pix.sizeimage); + vb2_set_plane_payload(&buffer->vb.vb2_buf, 0, + vfh->format.fmt.pix.sizeimage); buffer->dma = addr; return 0; @@ -380,8 +382,9 @@ static int isp_video_buffer_prepare(struct vb2_buffer *buf) */ static void isp_video_buffer_queue(struct vb2_buffer *buf) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(buf); struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue); - struct isp_buffer *buffer = to_isp_buffer(buf); + struct isp_buffer *buffer = to_isp_buffer(vbuf); struct isp_video *video = vfh->video; struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); enum isp_pipeline_state state; @@ -392,7 +395,7 @@ static void isp_video_buffer_queue(struct vb2_buffer *buf) spin_lock_irqsave(&video->irqlock, flags); if (unlikely(video->error)) { - vb2_buffer_done(&buffer->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_ERROR); spin_unlock_irqrestore(&video->irqlock, flags); return; } @@ -464,7 +467,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.v4l2_buf.timestamp); + v4l2_get_timestamp(&buf->vb.timestamp); /* Do frame number propagation only if this is the output video node. * Frame number either comes from the CSI receivers or it gets @@ -473,15 +476,15 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) * first, so the input number might lag behind by 1 in some cases. */ if (video == pipe->output && !pipe->do_propagation) - buf->vb.v4l2_buf.sequence = + buf->vb.sequence = atomic_inc_return(&pipe->frame_number); else - buf->vb.v4l2_buf.sequence = atomic_read(&pipe->frame_number); + buf->vb.sequence = atomic_read(&pipe->frame_number); if (pipe->field != V4L2_FIELD_NONE) - buf->vb.v4l2_buf.sequence /= 2; + buf->vb.sequence /= 2; - buf->vb.v4l2_buf.field = pipe->field; + buf->vb.field = pipe->field; /* Report pipeline errors to userspace on the capture device side. */ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) { @@ -491,7 +494,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) state = VB2_BUF_STATE_DONE; } - vb2_buffer_done(&buf->vb, state); + vb2_buffer_done(&buf->vb.vb2_buf, state); spin_lock_irqsave(&video->irqlock, flags); @@ -546,7 +549,7 @@ void omap3isp_video_cancel_stream(struct isp_video *video) buf = list_first_entry(&video->dmaqueue, struct isp_buffer, irqlist); list_del(&buf->irqlist); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } video->error = true; diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h index 4071dd7060ea..bcf0e0acc8f3 100644 --- a/drivers/media/platform/omap3isp/ispvideo.h +++ b/drivers/media/platform/omap3isp/ispvideo.h @@ -20,7 +20,7 @@ #include <media/media-entity.h> #include <media/v4l2-dev.h> #include <media/v4l2-fh.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #define ISP_VIDEO_DRIVER_NAME "ispvideo" #define ISP_VIDEO_DRIVER_VERSION "0.0.2" @@ -122,7 +122,7 @@ static inline int isp_pipeline_ready(struct isp_pipeline *pipe) * @dma: DMA address */ struct isp_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head irqlist; dma_addr_t dma; }; diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c index 2973f070d328..f8e3e83c52a2 100644 --- a/drivers/media/platform/rcar_jpu.c +++ b/drivers/media/platform/rcar_jpu.c @@ -37,7 +37,7 @@ #include <media/v4l2-fh.h> #include <media/v4l2-mem2mem.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> @@ -471,7 +471,7 @@ static const char *error_to_text[16] = { "Unknown" }; -static struct jpu_buffer *vb2_to_jpu_buffer(struct vb2_buffer *vb) +static struct jpu_buffer *vb2_to_jpu_buffer(struct vb2_v4l2_buffer *vb) { struct v4l2_m2m_buffer *b = container_of(vb, struct v4l2_m2m_buffer, vb); @@ -1015,10 +1015,11 @@ error_free: * ============================================================================ */ static int jpu_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + 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; @@ -1044,6 +1045,7 @@ static int jpu_queue_setup(struct vb2_queue *vq, static int jpu_buf_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct jpu_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct jpu_q_data *q_data; unsigned int i; @@ -1051,9 +1053,9 @@ static int jpu_buf_prepare(struct vb2_buffer *vb) q_data = jpu_get_q_data(ctx, vb->vb2_queue->type); if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { - if (vb->v4l2_buf.field == V4L2_FIELD_ANY) - vb->v4l2_buf.field = V4L2_FIELD_NONE; - if (vb->v4l2_buf.field != V4L2_FIELD_NONE) { + if (vbuf->field == V4L2_FIELD_ANY) + vbuf->field = V4L2_FIELD_NONE; + if (vbuf->field != V4L2_FIELD_NONE) { dev_err(ctx->jpu->dev, "%s field isn't supported\n", __func__); return -EINVAL; @@ -1080,10 +1082,11 @@ static int jpu_buf_prepare(struct vb2_buffer *vb) static void jpu_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct jpu_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); if (!ctx->encoder && V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { - struct jpu_buffer *jpu_buf = vb2_to_jpu_buffer(vb); + struct jpu_buffer *jpu_buf = vb2_to_jpu_buffer(vbuf); struct jpu_q_data *q_data, adjust; void *buffer = vb2_plane_vaddr(vb, 0); unsigned long buf_size = vb2_get_plane_payload(vb, 0); @@ -1117,7 +1120,7 @@ static void jpu_buf_queue(struct vb2_buffer *vb) } if (ctx->fh.m2m_ctx) - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); return; @@ -1128,14 +1131,15 @@ format_error: static void jpu_buf_finish(struct vb2_buffer *vb) { - struct jpu_buffer *jpu_buf = vb2_to_jpu_buffer(vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct jpu_buffer *jpu_buf = vb2_to_jpu_buffer(vbuf); struct jpu_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct jpu_q_data *q_data = &ctx->out_q; enum v4l2_buf_type type = vb->vb2_queue->type; u8 *buffer; if (vb->state == VB2_BUF_STATE_DONE) - vb->v4l2_buf.sequence = jpu_get_q_data(ctx, type)->sequence++; + vbuf->sequence = jpu_get_q_data(ctx, type)->sequence++; if (!ctx->encoder || vb->state != VB2_BUF_STATE_DONE || V4L2_TYPE_IS_OUTPUT(type)) @@ -1144,9 +1148,9 @@ static void jpu_buf_finish(struct vb2_buffer *vb) buffer = vb2_plane_vaddr(vb, 0); memcpy(buffer, jpeg_hdrs[jpu_buf->compr_quality], JPU_JPEG_HDR_SIZE); - *(u16 *)(buffer + JPU_JPEG_HEIGHT_OFFSET) = + *(__be16 *)(buffer + JPU_JPEG_HEIGHT_OFFSET) = cpu_to_be16(q_data->format.height); - *(u16 *)(buffer + JPU_JPEG_WIDTH_OFFSET) = + *(__be16 *)(buffer + JPU_JPEG_WIDTH_OFFSET) = cpu_to_be16(q_data->format.width); *(buffer + JPU_JPEG_SUBS_OFFSET) = q_data->fmtinfo->subsampling; } @@ -1163,7 +1167,7 @@ static int jpu_start_streaming(struct vb2_queue *vq, unsigned count) static void jpu_stop_streaming(struct vb2_queue *vq) { struct jpu_ctx *ctx = vb2_get_drv_priv(vq); - struct vb2_buffer *vb; + struct vb2_v4l2_buffer *vb; unsigned long flags; for (;;) { @@ -1327,7 +1331,7 @@ static const struct v4l2_file_operations jpu_fops = { static void jpu_cleanup(struct jpu_ctx *ctx, bool reset) { /* remove current buffers and finish job */ - struct vb2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; unsigned long flags; spin_lock_irqsave(&ctx->jpu->lock, flags); @@ -1353,7 +1357,7 @@ static void jpu_device_run(void *priv) struct jpu *jpu = ctx->jpu; struct jpu_buffer *jpu_buf; struct jpu_q_data *q_data; - struct vb2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; unsigned int w, h, bpl; unsigned char num_planes, subsampling; unsigned long flags; @@ -1389,10 +1393,12 @@ static void jpu_device_run(void *priv) unsigned long src_1_addr, src_2_addr, dst_addr; unsigned int redu, inft; - dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); - src_1_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); + dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + src_1_addr = + vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); if (num_planes > 1) - src_2_addr = vb2_dma_contig_plane_dma_addr(src_buf, 1); + src_2_addr = vb2_dma_contig_plane_dma_addr( + &src_buf->vb2_buf, 1); else src_2_addr = src_1_addr + w * h; @@ -1453,10 +1459,12 @@ static void jpu_device_run(void *priv) return; } - src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); - dst_1_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); + src_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + dst_1_addr = + vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); if (q_data->fmtinfo->num_planes > 1) - dst_2_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1); + dst_2_addr = vb2_dma_contig_plane_dma_addr( + &dst_buf->vb2_buf, 1); else dst_2_addr = dst_1_addr + w * h; @@ -1511,7 +1519,7 @@ static irqreturn_t jpu_irq_handler(int irq, void *dev_id) { struct jpu *jpu = dev_id; struct jpu_ctx *curr_ctx; - struct vb2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; unsigned int int_status; int_status = jpu_read(jpu, JINTS); @@ -1547,18 +1555,18 @@ static irqreturn_t jpu_irq_handler(int irq, void *dev_id) unsigned long payload_size = jpu_read(jpu, JCDTCU) << 16 | jpu_read(jpu, JCDTCM) << 8 | jpu_read(jpu, JCDTCD); - vb2_set_plane_payload(dst_buf, 0, + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size + JPU_JPEG_HDR_SIZE); } - dst_buf->v4l2_buf.field = src_buf->v4l2_buf.field; - dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp; - if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TIMECODE) - dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode; - dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_buf->v4l2_buf.flags |= src_buf->v4l2_buf.flags & + dst_buf->field = src_buf->field; + dst_buf->timestamp = src_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->v4l2_buf.flags = src_buf->v4l2_buf.flags & + dst_buf->flags = src_buf->flags & (V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | V4L2_BUF_FLAG_TSTAMP_SRC_MASK); diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index 76e6289a5612..537b858cb94a 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c @@ -34,7 +34,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "camif-core.h" @@ -164,12 +164,12 @@ static int camif_reinitialize(struct camif_vp *vp) /* Release unused buffers */ while (!list_empty(&vp->pending_buf_q)) { buf = camif_pending_queue_pop(vp); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } while (!list_empty(&vp->active_buf_q)) { buf = camif_active_queue_pop(vp); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&camif->slock, flags); @@ -328,25 +328,19 @@ irqreturn_t s3c_camif_irq_handler(int irq, void *priv) !list_empty(&vp->active_buf_q)) { unsigned int index; struct camif_buffer *vbuf; - struct timeval *tv; - struct timespec ts; /* * Get previous DMA write buffer index: * 0 => DMA buffer 0, 2; * 1 => DMA buffer 1, 3. */ index = (CISTATUS_FRAMECNT(status) + 2) & 1; - - ktime_get_ts(&ts); vbuf = camif_active_queue_peek(vp, index); if (!WARN_ON(vbuf == NULL)) { /* Dequeue a filled buffer */ - tv = &vbuf->vb.v4l2_buf.timestamp; - tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC; - vbuf->vb.v4l2_buf.sequence = vp->frame_sequence++; - vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&vbuf->vb.timestamp); + vbuf->vb.sequence = vp->frame_sequence++; + vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); /* Set up an empty buffer at the DMA engine */ vbuf = camif_pending_queue_pop(vp); @@ -441,10 +435,11 @@ static void stop_streaming(struct vb2_queue *vq) camif_stop_capture(vp); } -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt, +static int 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; const struct v4l2_pix_format *pix = NULL; struct camif_vp *vp = vb2_get_drv_priv(vq); struct camif_dev *camif = vp->camif; @@ -496,13 +491,14 @@ static int buffer_prepare(struct vb2_buffer *vb) static void buffer_queue(struct vb2_buffer *vb) { - struct camif_buffer *buf = container_of(vb, struct camif_buffer, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct camif_buffer *buf = container_of(vbuf, struct camif_buffer, vb); struct camif_vp *vp = vb2_get_drv_priv(vb->vb2_queue); struct camif_dev *camif = vp->camif; unsigned long flags; spin_lock_irqsave(&camif->slock, flags); - WARN_ON(camif_prepare_addr(vp, &buf->vb, &buf->paddr)); + WARN_ON(camif_prepare_addr(vp, &buf->vb.vb2_buf, &buf->paddr)); if (!(vp->state & ST_VP_STREAMING) && vp->active_buffers < 2) { /* Schedule an empty buffer in H/W */ diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c index f47b332f0418..1ba9bb08f5da 100644 --- a/drivers/media/platform/s3c-camif/camif-core.c +++ b/drivers/media/platform/s3c-camif/camif-core.c @@ -32,7 +32,7 @@ #include <media/media-device.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "camif-core.h" diff --git a/drivers/media/platform/s3c-camif/camif-core.h b/drivers/media/platform/s3c-camif/camif-core.h index 35d2fcdc0036..adaf1969ef63 100644 --- a/drivers/media/platform/s3c-camif/camif-core.h +++ b/drivers/media/platform/s3c-camif/camif-core.h @@ -25,7 +25,7 @@ #include <media/v4l2-dev.h> #include <media/v4l2-device.h> #include <media/v4l2-mediabus.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/s3c_camif.h> #define S3C_CAMIF_DRIVER_NAME "s3c-camif" @@ -322,7 +322,7 @@ struct camif_addr { * @index: an identifier of this buffer at the DMA engine */ struct camif_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; struct camif_addr paddr; unsigned int index; diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 421a7c3b595b..e1936d9d27da 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -23,7 +23,7 @@ #include <media/v4l2-mem2mem.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "g2d.h" @@ -101,7 +101,7 @@ static struct g2d_frame *get_frame(struct g2d_ctx *ctx, } } -static int g2d_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int g2d_queue_setup(struct vb2_queue *vq, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -134,8 +134,9 @@ static int g2d_buf_prepare(struct vb2_buffer *vb) static void g2d_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } static struct vb2_ops g2d_qops = { @@ -537,7 +538,7 @@ static irqreturn_t g2d_isr(int irq, void *prv) { struct g2d_dev *dev = prv; struct g2d_ctx *ctx = dev->curr; - struct vb2_buffer *src, *dst; + struct vb2_v4l2_buffer *src, *dst; g2d_clear_int(dev); clk_disable(dev->gate); @@ -550,11 +551,11 @@ static irqreturn_t g2d_isr(int irq, void *prv) BUG_ON(src == NULL); BUG_ON(dst == NULL); - dst->v4l2_buf.timecode = src->v4l2_buf.timecode; - dst->v4l2_buf.timestamp = src->v4l2_buf.timestamp; - dst->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst->v4l2_buf.flags |= - src->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst->timecode = src->timecode; + dst->timestamp = src->timestamp; + dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst->flags |= + src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 9690f9dcb0ca..4a608cbe0fdb 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -26,7 +26,7 @@ #include <linux/string.h> #include <media/v4l2-mem2mem.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "jpeg-core.h" @@ -626,6 +626,7 @@ static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx) return V4L2_JPEG_CHROMA_SUBSAMPLING_411; return exynos3250_decoded_subsampling[ctx->subsampling]; case SJPEG_EXYNOS4: + case SJPEG_EXYNOS5433: if (ctx->subsampling > 2) return V4L2_JPEG_CHROMA_SUBSAMPLING_420; return exynos4x12_decoded_subsampling[ctx->subsampling]; @@ -750,6 +751,208 @@ static void exynos4_jpeg_set_huff_tbl(void __iomem *base) ARRAY_SIZE(hactblg0)); } +static inline int __exynos4_huff_tbl(int class, int id, bool lenval) +{ + /* + * class: 0 - DC, 1 - AC + * id: 0 - Y, 1 - Cb/Cr + */ + if (class) { + if (id) + return lenval ? EXYNOS4_HUFF_TBL_HACCL : + EXYNOS4_HUFF_TBL_HACCV; + return lenval ? EXYNOS4_HUFF_TBL_HACLL : EXYNOS4_HUFF_TBL_HACLV; + + } + /* class == 0 */ + if (id) + return lenval ? EXYNOS4_HUFF_TBL_HDCCL : EXYNOS4_HUFF_TBL_HDCCV; + + return lenval ? EXYNOS4_HUFF_TBL_HDCLL : EXYNOS4_HUFF_TBL_HDCLV; +} + +static inline int exynos4_huff_tbl_len(int class, int id) +{ + return __exynos4_huff_tbl(class, id, true); +} + +static inline int exynos4_huff_tbl_val(int class, int id) +{ + return __exynos4_huff_tbl(class, id, false); +} + +static int get_byte(struct s5p_jpeg_buffer *buf); +static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word); +static void skip(struct s5p_jpeg_buffer *buf, long len); + +static void exynos4_jpeg_parse_decode_h_tbl(struct s5p_jpeg_ctx *ctx) +{ + struct s5p_jpeg *jpeg = ctx->jpeg; + struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + struct s5p_jpeg_buffer jpeg_buffer; + unsigned int word; + int c, x, components; + + jpeg_buffer.size = 2; /* Ls */ + jpeg_buffer.data = + (unsigned long)vb2_plane_vaddr(vb, 0) + ctx->out_q.sos + 2; + jpeg_buffer.curr = 0; + + word = 0; + + if (get_word_be(&jpeg_buffer, &word)) + return; + jpeg_buffer.size = (long)word - 2; + jpeg_buffer.data += 2; + jpeg_buffer.curr = 0; + + components = get_byte(&jpeg_buffer); + if (components == -1) + return; + while (components--) { + c = get_byte(&jpeg_buffer); + if (c == -1) + return; + x = get_byte(&jpeg_buffer); + if (x == -1) + return; + exynos4_jpeg_select_dec_h_tbl(jpeg->regs, c, + (((x >> 4) & 0x1) << 1) | (x & 0x1)); + } + +} + +static void exynos4_jpeg_parse_huff_tbl(struct s5p_jpeg_ctx *ctx) +{ + struct s5p_jpeg *jpeg = ctx->jpeg; + struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + struct s5p_jpeg_buffer jpeg_buffer; + unsigned int word; + int c, i, n, j; + + for (j = 0; j < ctx->out_q.dht.n; ++j) { + jpeg_buffer.size = ctx->out_q.dht.len[j]; + jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(vb, 0) + + ctx->out_q.dht.marker[j]; + jpeg_buffer.curr = 0; + + word = 0; + while (jpeg_buffer.curr < jpeg_buffer.size) { + char id, class; + + c = get_byte(&jpeg_buffer); + if (c == -1) + return; + id = c & 0xf; + class = (c >> 4) & 0xf; + n = 0; + for (i = 0; i < 16; ++i) { + c = get_byte(&jpeg_buffer); + if (c == -1) + return; + word |= c << ((i % 4) * 8); + if ((i + 1) % 4 == 0) { + writel(word, jpeg->regs + + exynos4_huff_tbl_len(class, id) + + (i / 4) * 4); + word = 0; + } + n += c; + } + word = 0; + for (i = 0; i < n; ++i) { + c = get_byte(&jpeg_buffer); + if (c == -1) + return; + word |= c << ((i % 4) * 8); + if ((i + 1) % 4 == 0) { + writel(word, jpeg->regs + + exynos4_huff_tbl_val(class, id) + + (i / 4) * 4); + word = 0; + } + } + if (i % 4) { + writel(word, jpeg->regs + + exynos4_huff_tbl_val(class, id) + (i / 4) * 4); + } + word = 0; + } + } +} + +static void exynos4_jpeg_parse_decode_q_tbl(struct s5p_jpeg_ctx *ctx) +{ + struct s5p_jpeg *jpeg = ctx->jpeg; + struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + struct s5p_jpeg_buffer jpeg_buffer; + int c, x, components; + + jpeg_buffer.size = ctx->out_q.sof_len; + jpeg_buffer.data = + (unsigned long)vb2_plane_vaddr(vb, 0) + ctx->out_q.sof; + jpeg_buffer.curr = 0; + + skip(&jpeg_buffer, 5); /* P, Y, X */ + components = get_byte(&jpeg_buffer); + if (components == -1) + return; + + exynos4_jpeg_set_dec_components(jpeg->regs, components); + + while (components--) { + c = get_byte(&jpeg_buffer); + if (c == -1) + return; + skip(&jpeg_buffer, 1); + x = get_byte(&jpeg_buffer); + if (x == -1) + return; + exynos4_jpeg_select_dec_q_tbl(jpeg->regs, c, x); + } +} + +static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx *ctx) +{ + struct s5p_jpeg *jpeg = ctx->jpeg; + struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + struct s5p_jpeg_buffer jpeg_buffer; + unsigned int word; + int c, i, j; + + for (j = 0; j < ctx->out_q.dqt.n; ++j) { + jpeg_buffer.size = ctx->out_q.dqt.len[j]; + jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(vb, 0) + + ctx->out_q.dqt.marker[j]; + jpeg_buffer.curr = 0; + + word = 0; + while (jpeg_buffer.size - jpeg_buffer.curr >= 65) { + char id; + + c = get_byte(&jpeg_buffer); + if (c == -1) + return; + id = c & 0xf; + /* nonzero means extended mode - not supported */ + if ((c >> 4) & 0xf) + return; + for (i = 0; i < 64; ++i) { + c = get_byte(&jpeg_buffer); + if (c == -1) + return; + word |= c << ((i % 4) * 8); + if ((i + 1) % 4 == 0) { + writel(word, jpeg->regs + + EXYNOS4_QTBL_CONTENT(id) + (i / 4) * 4); + word = 0; + } + } + word = 0; + } + } +} + /* * ============================================================================ * Device file operations @@ -894,8 +1097,11 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, unsigned long buffer, unsigned long size, struct s5p_jpeg_ctx *ctx) { - int c, components = 0, notfound; - unsigned int height, width, word, subsampling = 0; + int c, components = 0, notfound, n_dht = 0, n_dqt = 0; + unsigned int height, width, word, subsampling = 0, sos = 0, sof = 0, + sof_len = 0; + unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER], + dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER]; long length; struct s5p_jpeg_buffer jpeg_buffer; @@ -904,7 +1110,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, jpeg_buffer.curr = 0; notfound = 1; - while (notfound) { + while (notfound || !sos) { c = get_byte(&jpeg_buffer); if (c == -1) return false; @@ -923,6 +1129,11 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, case SOF0: if (get_word_be(&jpeg_buffer, &word)) break; + length = (long)word - 2; + if (!length) + return false; + sof = jpeg_buffer.curr; /* after 0xffc0 */ + sof_len = length; if (get_byte(&jpeg_buffer) == -1) break; if (get_word_be(&jpeg_buffer, &height)) @@ -932,7 +1143,6 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, components = get_byte(&jpeg_buffer); if (components == -1) break; - notfound = 0; if (components == 1) { subsampling = 0x33; @@ -941,8 +1151,40 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, subsampling = get_byte(&jpeg_buffer); skip(&jpeg_buffer, 1); } - + if (components > 3) + return false; skip(&jpeg_buffer, components * 2); + notfound = 0; + break; + + case DQT: + if (get_word_be(&jpeg_buffer, &word)) + break; + length = (long)word - 2; + if (!length) + return false; + if (n_dqt >= S5P_JPEG_MAX_MARKER) + return false; + dqt[n_dqt] = jpeg_buffer.curr; /* after 0xffdb */ + dqt_len[n_dqt++] = length; + skip(&jpeg_buffer, length); + break; + + case DHT: + if (get_word_be(&jpeg_buffer, &word)) + break; + length = (long)word - 2; + if (!length) + return false; + if (n_dht >= S5P_JPEG_MAX_MARKER) + return false; + dht[n_dht] = jpeg_buffer.curr; /* after 0xffc4 */ + dht_len[n_dht++] = length; + skip(&jpeg_buffer, length); + break; + + case SOS: + sos = jpeg_buffer.curr - 2; /* 0xffda */ break; /* skip payload-less markers */ @@ -963,7 +1205,20 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, } result->w = width; result->h = height; - result->size = components; + result->sos = sos; + result->dht.n = n_dht; + while (n_dht--) { + result->dht.marker[n_dht] = dht[n_dht]; + result->dht.len[n_dht] = dht_len[n_dht]; + } + result->dqt.n = n_dqt; + while (n_dqt--) { + result->dqt.marker[n_dqt] = dqt[n_dqt]; + result->dqt.len[n_dqt] = dqt_len[n_dqt]; + } + result->sof = sof; + result->sof_len = sof_len; + result->size = result->components = components; switch (subsampling) { case 0x11: @@ -982,7 +1237,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, return false; } - return !notfound; + return !notfound && sos; } static int s5p_jpeg_querycap(struct file *file, void *priv, @@ -1226,8 +1481,7 @@ static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } - if ((ctx->jpeg->variant->version != SJPEG_EXYNOS4) || - (ctx->mode != S5P_JPEG_DECODE)) + if (!ctx->jpeg->variant->hw_ex4_compat || ctx->mode != S5P_JPEG_DECODE) goto exit; /* @@ -1350,7 +1604,7 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu * page fault calculate proper buffer size in such a case. */ - if (ct->jpeg->variant->version == SJPEG_EXYNOS4 && + if (ct->jpeg->variant->hw_ex4_compat && f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE) q_data->size = exynos4_jpeg_get_output_buffer_size(ct, f, @@ -1889,9 +2143,36 @@ static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx) vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + if (jpeg->variant->version == SJPEG_EXYNOS5433 && + ctx->mode == S5P_JPEG_DECODE) + jpeg_addr += ctx->out_q.sos; exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr); } +static inline void exynos4_jpeg_set_img_fmt(void __iomem *base, + unsigned int img_fmt) +{ + __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS4); +} + +static inline void exynos5433_jpeg_set_img_fmt(void __iomem *base, + unsigned int img_fmt) +{ + __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS5433); +} + +static inline void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, + unsigned int out_fmt) +{ + __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS4); +} + +static inline void exynos5433_jpeg_set_enc_out_fmt(void __iomem *base, + unsigned int out_fmt) +{ + __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS5433); +} + static void exynos4_jpeg_device_run(void *priv) { struct s5p_jpeg_ctx *ctx = priv; @@ -1899,11 +2180,11 @@ static void exynos4_jpeg_device_run(void *priv) unsigned int bitstream_size; unsigned long flags; - spin_lock_irqsave(&ctx->jpeg->slock, flags); + spin_lock_irqsave(&jpeg->slock, flags); if (ctx->mode == S5P_JPEG_ENCODE) { exynos4_jpeg_sw_reset(jpeg->regs); - exynos4_jpeg_set_interrupt(jpeg->regs); + exynos4_jpeg_set_interrupt(jpeg->regs, jpeg->variant->version); exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1); exynos4_jpeg_set_huff_tbl(jpeg->regs); @@ -1920,27 +2201,56 @@ static void exynos4_jpeg_device_run(void *priv) exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w, ctx->cap_q.h); - exynos4_jpeg_set_enc_out_fmt(jpeg->regs, ctx->subsampling); - exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->out_q.fmt->fourcc); + if (ctx->jpeg->variant->version == SJPEG_EXYNOS4) { + exynos4_jpeg_set_enc_out_fmt(jpeg->regs, + ctx->subsampling); + exynos4_jpeg_set_img_fmt(jpeg->regs, + ctx->out_q.fmt->fourcc); + } else { + exynos5433_jpeg_set_enc_out_fmt(jpeg->regs, + ctx->subsampling); + exynos5433_jpeg_set_img_fmt(jpeg->regs, + ctx->out_q.fmt->fourcc); + } exynos4_jpeg_set_img_addr(ctx); exynos4_jpeg_set_jpeg_addr(ctx); exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs, ctx->out_q.fmt->fourcc); } else { exynos4_jpeg_sw_reset(jpeg->regs); - exynos4_jpeg_set_interrupt(jpeg->regs); + exynos4_jpeg_set_interrupt(jpeg->regs, + jpeg->variant->version); exynos4_jpeg_set_img_addr(ctx); exynos4_jpeg_set_jpeg_addr(ctx); - exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->cap_q.fmt->fourcc); - bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32); + if (jpeg->variant->version == SJPEG_EXYNOS5433) { + exynos4_jpeg_parse_huff_tbl(ctx); + exynos4_jpeg_parse_decode_h_tbl(ctx); + + exynos4_jpeg_parse_q_tbl(ctx); + exynos4_jpeg_parse_decode_q_tbl(ctx); + + exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1); + + exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w, + ctx->cap_q.h); + exynos5433_jpeg_set_enc_out_fmt(jpeg->regs, + ctx->subsampling); + exynos5433_jpeg_set_img_fmt(jpeg->regs, + ctx->cap_q.fmt->fourcc); + bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 16); + } else { + exynos4_jpeg_set_img_fmt(jpeg->regs, + ctx->cap_q.fmt->fourcc); + bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32); + } exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size); } exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode); - spin_unlock_irqrestore(&ctx->jpeg->slock, flags); + spin_unlock_irqrestore(&jpeg->slock, flags); } static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx) @@ -2120,7 +2430,7 @@ static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = { */ static int s5p_jpeg_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -2170,6 +2480,7 @@ static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb) static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); if (ctx->mode == S5P_JPEG_DECODE && @@ -2187,13 +2498,24 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) q_data = &ctx->out_q; q_data->w = tmp.w; q_data->h = tmp.h; + q_data->sos = tmp.sos; + memcpy(q_data->dht.marker, tmp.dht.marker, + sizeof(tmp.dht.marker)); + memcpy(q_data->dht.len, tmp.dht.len, sizeof(tmp.dht.len)); + q_data->dht.n = tmp.dht.n; + memcpy(q_data->dqt.marker, tmp.dqt.marker, + sizeof(tmp.dqt.marker)); + memcpy(q_data->dqt.len, tmp.dqt.len, sizeof(tmp.dqt.len)); + q_data->dqt.n = tmp.dqt.n; + q_data->sof = tmp.sof; + q_data->sof_len = tmp.sof_len; q_data = &ctx->cap_q; q_data->w = tmp.w; q_data->h = tmp.h; } - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count) @@ -2264,7 +2586,7 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id) { struct s5p_jpeg *jpeg = dev_id; struct s5p_jpeg_ctx *curr_ctx; - struct vb2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; unsigned long payload_size = 0; enum vb2_buffer_state state = VB2_BUF_STATE_DONE; bool enc_jpeg_too_large = false; @@ -2298,15 +2620,15 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id) payload_size = s5p_jpeg_compressed_size(jpeg->regs); } - dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode; - dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp; - dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_buf->v4l2_buf.flags |= - src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_buf->timecode = src_buf->timecode; + dst_buf->timestamp = src_buf->timestamp; + dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_buf->flags |= + src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; v4l2_m2m_buf_done(src_buf, state); if (curr_ctx->mode == S5P_JPEG_ENCODE) - vb2_set_plane_payload(dst_buf, 0, payload_size); + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size); v4l2_m2m_buf_done(dst_buf, state); v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx); @@ -2321,7 +2643,7 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id) static irqreturn_t exynos4_jpeg_irq(int irq, void *priv) { unsigned int int_status; - struct vb2_buffer *src_vb, *dst_vb; + struct vb2_v4l2_buffer *src_vb, *dst_vb; struct s5p_jpeg *jpeg = priv; struct s5p_jpeg_ctx *curr_ctx; unsigned long payload_size = 0; @@ -2363,7 +2685,8 @@ static irqreturn_t exynos4_jpeg_irq(int irq, void *priv) if (jpeg->irq_ret == OK_ENC_OR_DEC) { if (curr_ctx->mode == S5P_JPEG_ENCODE) { payload_size = exynos4_jpeg_get_stream_size(jpeg->regs); - vb2_set_plane_payload(dst_vb, 0, payload_size); + vb2_set_plane_payload(&dst_vb->vb2_buf, + 0, payload_size); } v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); @@ -2373,7 +2696,8 @@ static irqreturn_t exynos4_jpeg_irq(int irq, void *priv) } v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx); - curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs); + if (jpeg->variant->version == SJPEG_EXYNOS4) + curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs); spin_unlock(&jpeg->slock); return IRQ_HANDLED; @@ -2383,7 +2707,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) { struct s5p_jpeg *jpeg = dev_id; struct s5p_jpeg_ctx *curr_ctx; - struct vb2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; unsigned long payload_size = 0; enum vb2_buffer_state state = VB2_BUF_STATE_DONE; bool interrupt_timeout = false; @@ -2427,12 +2751,12 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx); - dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode; - dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp; + dst_buf->timecode = src_buf->timecode; + dst_buf->timestamp = src_buf->timestamp; v4l2_m2m_buf_done(src_buf, state); if (curr_ctx->mode == S5P_JPEG_ENCODE) - vb2_set_plane_payload(dst_buf, 0, payload_size); + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size); v4l2_m2m_buf_done(dst_buf, state); v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx); @@ -2455,7 +2779,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev) { struct s5p_jpeg *jpeg; struct resource *res; - int ret; + int i, ret; /* JPEG IP abstraction struct */ jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL); @@ -2490,23 +2814,21 @@ static int s5p_jpeg_probe(struct platform_device *pdev) } /* clocks */ - jpeg->clk = clk_get(&pdev->dev, "jpeg"); - if (IS_ERR(jpeg->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); - ret = PTR_ERR(jpeg->clk); - return ret; + for (i = 0; i < jpeg->variant->num_clocks; i++) { + jpeg->clocks[i] = devm_clk_get(&pdev->dev, + jpeg->variant->clk_names[i]); + if (IS_ERR(jpeg->clocks[i])) { + dev_err(&pdev->dev, "failed to get clock: %s\n", + jpeg->variant->clk_names[i]); + return PTR_ERR(jpeg->clocks[i]); + } } - dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk); - - jpeg->sclk = clk_get(&pdev->dev, "sclk"); - if (IS_ERR(jpeg->sclk)) - dev_info(&pdev->dev, "sclk clock not available\n"); /* v4l2 device */ ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev); if (ret) { dev_err(&pdev->dev, "Failed to register v4l2 device\n"); - goto clk_get_rollback; + return ret; } /* mem2mem device */ @@ -2603,17 +2925,13 @@ m2m_init_rollback: device_register_rollback: v4l2_device_unregister(&jpeg->v4l2_dev); -clk_get_rollback: - clk_put(jpeg->clk); - if (!IS_ERR(jpeg->sclk)) - clk_put(jpeg->sclk); - return ret; } static int s5p_jpeg_remove(struct platform_device *pdev) { struct s5p_jpeg *jpeg = platform_get_drvdata(pdev); + int i; pm_runtime_disable(jpeg->dev); @@ -2624,15 +2942,10 @@ static int s5p_jpeg_remove(struct platform_device *pdev) v4l2_device_unregister(&jpeg->v4l2_dev); if (!pm_runtime_status_suspended(&pdev->dev)) { - clk_disable_unprepare(jpeg->clk); - if (!IS_ERR(jpeg->sclk)) - clk_disable_unprepare(jpeg->sclk); + for (i = jpeg->variant->num_clocks - 1; i >= 0; i--) + clk_disable_unprepare(jpeg->clocks[i]); } - clk_put(jpeg->clk); - if (!IS_ERR(jpeg->sclk)) - clk_put(jpeg->sclk); - return 0; } @@ -2640,10 +2953,10 @@ static int s5p_jpeg_remove(struct platform_device *pdev) static int s5p_jpeg_runtime_suspend(struct device *dev) { struct s5p_jpeg *jpeg = dev_get_drvdata(dev); + int i; - clk_disable_unprepare(jpeg->clk); - if (!IS_ERR(jpeg->sclk)) - clk_disable_unprepare(jpeg->sclk); + for (i = jpeg->variant->num_clocks - 1; i >= 0; i--) + clk_disable_unprepare(jpeg->clocks[i]); return 0; } @@ -2652,16 +2965,15 @@ static int s5p_jpeg_runtime_resume(struct device *dev) { struct s5p_jpeg *jpeg = dev_get_drvdata(dev); unsigned long flags; - int ret; + int i, ret; - ret = clk_prepare_enable(jpeg->clk); - if (ret < 0) - return ret; - - if (!IS_ERR(jpeg->sclk)) { - ret = clk_prepare_enable(jpeg->sclk); - if (ret < 0) + for (i = 0; i < jpeg->variant->num_clocks; i++) { + ret = clk_prepare_enable(jpeg->clocks[i]); + if (ret) { + while (--i > 0) + clk_disable_unprepare(jpeg->clocks[i]); return ret; + } } spin_lock_irqsave(&jpeg->slock, flags); @@ -2715,6 +3027,8 @@ static struct s5p_jpeg_variant s5p_jpeg_drvdata = { .jpeg_irq = s5p_jpeg_irq, .m2m_ops = &s5p_jpeg_m2m_ops, .fmt_ver_flag = SJPEG_FMT_FLAG_S5P, + .clk_names = {"jpeg"}, + .num_clocks = 1, }; static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = { @@ -2723,6 +3037,8 @@ static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = { .m2m_ops = &exynos3250_jpeg_m2m_ops, .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250, .hw3250_compat = 1, + .clk_names = {"jpeg", "sclk"}, + .num_clocks = 2, }; static struct s5p_jpeg_variant exynos4_jpeg_drvdata = { @@ -2731,6 +3047,9 @@ static struct s5p_jpeg_variant exynos4_jpeg_drvdata = { .m2m_ops = &exynos4_jpeg_m2m_ops, .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4, .htbl_reinit = 1, + .clk_names = {"jpeg"}, + .num_clocks = 1, + .hw_ex4_compat = 1, }; static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = { @@ -2740,6 +3059,19 @@ static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = { .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250, /* intentionally 3250 */ .hw3250_compat = 1, .htbl_reinit = 1, + .clk_names = {"jpeg"}, + .num_clocks = 1, +}; + +static struct s5p_jpeg_variant exynos5433_jpeg_drvdata = { + .version = SJPEG_EXYNOS5433, + .jpeg_irq = exynos4_jpeg_irq, + .m2m_ops = &exynos4_jpeg_m2m_ops, + .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4, + .htbl_reinit = 1, + .clk_names = {"pclk", "aclk", "aclk_xiu", "sclk"}, + .num_clocks = 4, + .hw_ex4_compat = 1, }; static const struct of_device_id samsung_jpeg_match[] = { @@ -2758,6 +3090,9 @@ static const struct of_device_id samsung_jpeg_match[] = { }, { .compatible = "samsung,exynos5420-jpeg", .data = &exynos5420_jpeg_drvdata, + }, { + .compatible = "samsung,exynos5433-jpeg", + .data = &exynos5433_jpeg_drvdata, }, {}, }; diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h index 7d9a9ed19cea..9b1db0934909 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.h @@ -20,6 +20,8 @@ #define S5P_JPEG_M2M_NAME "s5p-jpeg" +#define JPEG_MAX_CLOCKS 4 + /* JPEG compression quality setting */ #define S5P_JPEG_COMPR_QUAL_BEST 0 #define S5P_JPEG_COMPR_QUAL_WORST 3 @@ -40,9 +42,12 @@ /* a selection of JPEG markers */ #define TEM 0x01 #define SOF0 0xc0 +#define DHT 0xc4 #define RST 0xd0 #define SOI 0xd8 #define EOI 0xd9 +#define SOS 0xda +#define DQT 0xdb #define DHP 0xde /* Flags that indicate a format can be used for capture/output */ @@ -66,12 +71,15 @@ #define SJPEG_SUBSAMPLING_422 0x21 #define SJPEG_SUBSAMPLING_420 0x22 +#define S5P_JPEG_MAX_MARKER 4 + /* Version numbers */ enum sjpeg_version { SJPEG_S5P, SJPEG_EXYNOS3250, SJPEG_EXYNOS4, SJPEG_EXYNOS5420, + SJPEG_EXYNOS5433, }; enum exynos4_jpeg_result { @@ -100,8 +108,7 @@ enum exynos4_jpeg_img_quality_level { * @m2m_dev: v4l2 mem2mem device data * @regs: JPEG IP registers mapping * @irq: JPEG IP irq - * @clk: JPEG IP clock - * @sclk: Exynos3250 JPEG IP special clock + * @clocks: JPEG IP clock(s) * @dev: JPEG IP struct device * @alloc_ctx: videobuf2 memory allocator's context * @variant: driver variant to be used @@ -121,8 +128,7 @@ struct s5p_jpeg { void __iomem *regs; unsigned int irq; enum exynos4_jpeg_result irq_ret; - struct clk *clk; - struct clk *sclk; + struct clk *clocks[JPEG_MAX_CLOCKS]; struct device *dev; void *alloc_ctx; struct s5p_jpeg_variant *variant; @@ -134,8 +140,11 @@ struct s5p_jpeg_variant { unsigned int fmt_ver_flag; unsigned int hw3250_compat:1; unsigned int htbl_reinit:1; + unsigned int hw_ex4_compat:1; struct v4l2_m2m_ops *m2m_ops; irqreturn_t (*jpeg_irq)(int irq, void *priv); + const char *clk_names[JPEG_MAX_CLOCKS]; + int num_clocks; }; /** @@ -161,16 +170,40 @@ struct s5p_jpeg_fmt { }; /** + * s5p_jpeg_marker - collection of markers from jpeg header + * @marker: markers' positions relative to the buffer beginning + * @len: markers' payload lengths (without length field) + * @n: number of markers in collection + */ +struct s5p_jpeg_marker { + u32 marker[S5P_JPEG_MAX_MARKER]; + u32 len[S5P_JPEG_MAX_MARKER]; + u32 n; +}; + +/** * s5p_jpeg_q_data - parameters of one queue * @fmt: driver-specific format of this queue * @w: image width * @h: image height + * @sos: SOS marker's position relative to the buffer beginning + * @dht: DHT markers' positions relative to the buffer beginning + * @dqt: DQT markers' positions relative to the buffer beginning + * @sof: SOF0 marker's postition relative to the buffer beginning + * @sof_len: SOF0 marker's payload length (without length field itself) + * @components: number of image components * @size: image buffer size in bytes */ struct s5p_jpeg_q_data { struct s5p_jpeg_fmt *fmt; u32 w; u32 h; + u32 sos; + struct s5p_jpeg_marker dht; + struct s5p_jpeg_marker dqt; + u32 sof; + u32 sof_len; + u32 components; u32 size; }; diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c index ab6d6f43c96f..0912d0a892e2 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c @@ -45,9 +45,20 @@ void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode) } } -void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt) +void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt, + unsigned int version) { unsigned int reg; + unsigned int exynos4_swap_chroma_cbcr; + unsigned int exynos4_swap_chroma_crcb; + + if (version == SJPEG_EXYNOS4) { + exynos4_swap_chroma_cbcr = EXYNOS4_SWAP_CHROMA_CBCR; + exynos4_swap_chroma_crcb = EXYNOS4_SWAP_CHROMA_CRCB; + } else { + exynos4_swap_chroma_cbcr = EXYNOS5433_SWAP_CHROMA_CBCR; + exynos4_swap_chroma_crcb = EXYNOS5433_SWAP_CHROMA_CRCB; + } reg = readl(base + EXYNOS4_IMG_FMT_REG) & EXYNOS4_ENC_IN_FMT_MASK; /* clear except enc format */ @@ -67,48 +78,48 @@ void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt) case V4L2_PIX_FMT_NV24: reg = reg | EXYNOS4_ENC_YUV_444_IMG | EXYNOS4_YUV_444_IP_YUV_444_2P_IMG | - EXYNOS4_SWAP_CHROMA_CBCR; + exynos4_swap_chroma_cbcr; break; case V4L2_PIX_FMT_NV42: reg = reg | EXYNOS4_ENC_YUV_444_IMG | EXYNOS4_YUV_444_IP_YUV_444_2P_IMG | - EXYNOS4_SWAP_CHROMA_CRCB; + exynos4_swap_chroma_crcb; break; case V4L2_PIX_FMT_YUYV: reg = reg | EXYNOS4_DEC_YUV_422_IMG | EXYNOS4_YUV_422_IP_YUV_422_1P_IMG | - EXYNOS4_SWAP_CHROMA_CBCR; + exynos4_swap_chroma_cbcr; break; case V4L2_PIX_FMT_YVYU: reg = reg | EXYNOS4_DEC_YUV_422_IMG | EXYNOS4_YUV_422_IP_YUV_422_1P_IMG | - EXYNOS4_SWAP_CHROMA_CRCB; + exynos4_swap_chroma_crcb; break; case V4L2_PIX_FMT_NV16: reg = reg | EXYNOS4_DEC_YUV_422_IMG | EXYNOS4_YUV_422_IP_YUV_422_2P_IMG | - EXYNOS4_SWAP_CHROMA_CBCR; + exynos4_swap_chroma_cbcr; break; case V4L2_PIX_FMT_NV61: reg = reg | EXYNOS4_DEC_YUV_422_IMG | EXYNOS4_YUV_422_IP_YUV_422_2P_IMG | - EXYNOS4_SWAP_CHROMA_CRCB; + exynos4_swap_chroma_crcb; break; case V4L2_PIX_FMT_NV12: reg = reg | EXYNOS4_DEC_YUV_420_IMG | EXYNOS4_YUV_420_IP_YUV_420_2P_IMG | - EXYNOS4_SWAP_CHROMA_CBCR; + exynos4_swap_chroma_cbcr; break; case V4L2_PIX_FMT_NV21: reg = reg | EXYNOS4_DEC_YUV_420_IMG | EXYNOS4_YUV_420_IP_YUV_420_2P_IMG | - EXYNOS4_SWAP_CHROMA_CRCB; + exynos4_swap_chroma_crcb; break; case V4L2_PIX_FMT_YUV420: reg = reg | EXYNOS4_DEC_YUV_420_IMG | EXYNOS4_YUV_420_IP_YUV_420_3P_IMG | - EXYNOS4_SWAP_CHROMA_CBCR; + exynos4_swap_chroma_cbcr; break; default: break; @@ -118,12 +129,14 @@ void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt) writel(reg, base + EXYNOS4_IMG_FMT_REG); } -void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt) +void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt, + unsigned int version) { unsigned int reg; reg = readl(base + EXYNOS4_IMG_FMT_REG) & - ~EXYNOS4_ENC_FMT_MASK; /* clear enc format */ + ~(version == SJPEG_EXYNOS4 ? EXYNOS4_ENC_FMT_MASK : + EXYNOS5433_ENC_FMT_MASK); /* clear enc format */ switch (out_fmt) { case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY: @@ -149,9 +162,18 @@ void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt) writel(reg, base + EXYNOS4_IMG_FMT_REG); } -void exynos4_jpeg_set_interrupt(void __iomem *base) +void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version) { - writel(EXYNOS4_INT_EN_ALL, base + EXYNOS4_INT_EN_REG); + unsigned int reg; + + if (version == SJPEG_EXYNOS4) { + reg = readl(base + EXYNOS4_INT_EN_REG) & ~EXYNOS4_INT_EN_MASK; + writel(reg | EXYNOS4_INT_EN_ALL, base + EXYNOS4_INT_EN_REG); + } else { + reg = readl(base + EXYNOS4_INT_EN_REG) & + ~EXYNOS5433_INT_EN_MASK; + writel(reg | EXYNOS5433_INT_EN_ALL, base + EXYNOS4_INT_EN_REG); + } } unsigned int exynos4_jpeg_get_int_status(void __iomem *base) @@ -234,6 +256,36 @@ void exynos4_jpeg_set_encode_tbl_select(void __iomem *base, writel(reg, base + EXYNOS4_TBL_SEL_REG); } +void exynos4_jpeg_set_dec_components(void __iomem *base, int n) +{ + unsigned int reg; + + reg = readl(base + EXYNOS4_TBL_SEL_REG); + + reg |= EXYNOS4_NF(n); + writel(reg, base + EXYNOS4_TBL_SEL_REG); +} + +void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x) +{ + unsigned int reg; + + reg = readl(base + EXYNOS4_TBL_SEL_REG); + + reg |= EXYNOS4_Q_TBL_COMP(c, x); + writel(reg, base + EXYNOS4_TBL_SEL_REG); +} + +void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x) +{ + unsigned int reg; + + reg = readl(base + EXYNOS4_TBL_SEL_REG); + + reg |= EXYNOS4_HUFF_TBL_COMP(c, x); + writel(reg, base + EXYNOS4_TBL_SEL_REG); +} + void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt) { if (fmt == V4L2_PIX_FMT_GREY) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h index c228d28a4bc7..cf6ec055d63a 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h @@ -15,10 +15,12 @@ void exynos4_jpeg_sw_reset(void __iomem *base); void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode); -void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt); -void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt); +void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt, + unsigned int version); +void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt, + unsigned int version); void exynos4_jpeg_set_enc_tbl(void __iomem *base); -void exynos4_jpeg_set_interrupt(void __iomem *base); +void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version); unsigned int exynos4_jpeg_get_int_status(void __iomem *base); void exynos4_jpeg_set_huf_table_enable(void __iomem *base, int value); void exynos4_jpeg_set_sys_int_enable(void __iomem *base, int value); @@ -30,6 +32,9 @@ void exynos4_jpeg_set_frame_buf_address(void __iomem *base, struct s5p_jpeg_addr *jpeg_addr); void exynos4_jpeg_set_encode_tbl_select(void __iomem *base, enum exynos4_jpeg_img_quality_level level); +void exynos4_jpeg_set_dec_components(void __iomem *base, int n); +void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x); +void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x); void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt); void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size); unsigned int exynos4_jpeg_get_stream_size(void __iomem *base); diff --git a/drivers/media/platform/s5p-jpeg/jpeg-regs.h b/drivers/media/platform/s5p-jpeg/jpeg-regs.h index 050fc440248f..1870400468b2 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-regs.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-regs.h @@ -231,12 +231,14 @@ /* JPEG INT Register bit */ #define EXYNOS4_INT_EN_MASK (0x1f << 0) +#define EXYNOS5433_INT_EN_MASK (0x1ff << 0) #define EXYNOS4_PROT_ERR_INT_EN (1 << 0) #define EXYNOS4_IMG_COMPLETION_INT_EN (1 << 1) #define EXYNOS4_DEC_INVALID_FORMAT_EN (1 << 2) #define EXYNOS4_MULTI_SCAN_ERROR_EN (1 << 3) #define EXYNOS4_FRAME_ERR_EN (1 << 4) #define EXYNOS4_INT_EN_ALL (0x1f << 0) +#define EXYNOS5433_INT_EN_ALL (0x1b6 << 0) #define EXYNOS4_MOD_REG_PROC_ENC (0 << 3) #define EXYNOS4_MOD_REG_PROC_DEC (1 << 3) @@ -296,6 +298,8 @@ #define EXYNOS4_ENC_FMT_SHIFT 24 #define EXYNOS4_ENC_FMT_MASK (3 << EXYNOS4_ENC_FMT_SHIFT) +#define EXYNOS5433_ENC_FMT_MASK (7 << EXYNOS4_ENC_FMT_SHIFT) + #define EXYNOS4_ENC_FMT_GRAY (0 << EXYNOS4_ENC_FMT_SHIFT) #define EXYNOS4_ENC_FMT_YUV_444 (1 << EXYNOS4_ENC_FMT_SHIFT) #define EXYNOS4_ENC_FMT_YUV_422 (2 << EXYNOS4_ENC_FMT_SHIFT) @@ -305,6 +309,8 @@ #define EXYNOS4_SWAP_CHROMA_CRCB (1 << 26) #define EXYNOS4_SWAP_CHROMA_CBCR (0 << 26) +#define EXYNOS5433_SWAP_CHROMA_CRCB (1 << 27) +#define EXYNOS5433_SWAP_CHROMA_CBCR (0 << 27) /* JPEG HUFF count Register bit */ #define EXYNOS4_HUFF_COUNT_MASK 0xffff @@ -316,35 +322,56 @@ #define EXYNOS4_DECODED_IMG_FMT_MASK 0x3 /* JPEG TBL SEL Register bit */ -#define EXYNOS4_Q_TBL_COMP1_0 (0 << 0) -#define EXYNOS4_Q_TBL_COMP1_1 (1 << 0) -#define EXYNOS4_Q_TBL_COMP1_2 (2 << 0) -#define EXYNOS4_Q_TBL_COMP1_3 (3 << 0) - -#define EXYNOS4_Q_TBL_COMP2_0 (0 << 2) -#define EXYNOS4_Q_TBL_COMP2_1 (1 << 2) -#define EXYNOS4_Q_TBL_COMP2_2 (2 << 2) -#define EXYNOS4_Q_TBL_COMP2_3 (3 << 2) - -#define EXYNOS4_Q_TBL_COMP3_0 (0 << 4) -#define EXYNOS4_Q_TBL_COMP3_1 (1 << 4) -#define EXYNOS4_Q_TBL_COMP3_2 (2 << 4) -#define EXYNOS4_Q_TBL_COMP3_3 (3 << 4) - -#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_0 (0 << 6) -#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1 (1 << 6) -#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_0 (2 << 6) -#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_1 (3 << 6) - -#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 (0 << 8) -#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_1 (1 << 8) -#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_0 (2 << 8) -#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_1 (3 << 8) - -#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_0 (0 << 10) -#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_1 (1 << 10) -#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_0 (2 << 10) -#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1 (3 << 10) +#define EXYNOS4_Q_TBL_COMP(c, n) ((n) << (((c) - 1) << 1)) + +#define EXYNOS4_Q_TBL_COMP1_0 EXYNOS4_Q_TBL_COMP(1, 0) +#define EXYNOS4_Q_TBL_COMP1_1 EXYNOS4_Q_TBL_COMP(1, 1) +#define EXYNOS4_Q_TBL_COMP1_2 EXYNOS4_Q_TBL_COMP(1, 2) +#define EXYNOS4_Q_TBL_COMP1_3 EXYNOS4_Q_TBL_COMP(1, 3) + +#define EXYNOS4_Q_TBL_COMP2_0 EXYNOS4_Q_TBL_COMP(2, 0) +#define EXYNOS4_Q_TBL_COMP2_1 EXYNOS4_Q_TBL_COMP(2, 1) +#define EXYNOS4_Q_TBL_COMP2_2 EXYNOS4_Q_TBL_COMP(2, 2) +#define EXYNOS4_Q_TBL_COMP2_3 EXYNOS4_Q_TBL_COMP(2, 3) + +#define EXYNOS4_Q_TBL_COMP3_0 EXYNOS4_Q_TBL_COMP(3, 0) +#define EXYNOS4_Q_TBL_COMP3_1 EXYNOS4_Q_TBL_COMP(3, 1) +#define EXYNOS4_Q_TBL_COMP3_2 EXYNOS4_Q_TBL_COMP(3, 2) +#define EXYNOS4_Q_TBL_COMP3_3 EXYNOS4_Q_TBL_COMP(3, 3) + +#define EXYNOS4_HUFF_TBL_COMP(c, n) ((n) << ((((c) - 1) << 1) + 6)) + +#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_0 \ + EXYNOS4_HUFF_TBL_COMP(1, 0) +#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1 \ + EXYNOS4_HUFF_TBL_COMP(1, 1) +#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_0 \ + EXYNOS4_HUFF_TBL_COMP(1, 2) +#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_1 \ + EXYNOS4_HUFF_TBL_COMP(1, 3) + +#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 \ + EXYNOS4_HUFF_TBL_COMP(2, 0) +#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_1 \ + EXYNOS4_HUFF_TBL_COMP(2, 1) +#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_0 \ + EXYNOS4_HUFF_TBL_COMP(2, 2) +#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_1 \ + EXYNOS4_HUFF_TBL_COMP(2, 3) + +#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_0 \ + EXYNOS4_HUFF_TBL_COMP(3, 0) +#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_1 \ + EXYNOS4_HUFF_TBL_COMP(3, 1) +#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_0 \ + EXYNOS4_HUFF_TBL_COMP(3, 2) +#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1 \ + EXYNOS4_HUFF_TBL_COMP(3, 3) + +#define EXYNOS4_NF_SHIFT 16 +#define EXYNOS4_NF_MASK 0xff +#define EXYNOS4_NF(x) \ + (((x) << EXYNOS4_NF_SHIFT) & EXYNOS4_NF_MASK) /* JPEG quantizer table register */ #define EXYNOS4_QTBL_CONTENT(n) (0x100 + (n) * 0x40) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 8de61dc1e142..3ffe2ecfd5ef 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -22,7 +22,7 @@ #include <media/v4l2-event.h> #include <linux/workqueue.h> #include <linux/of.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include "s5p_mfc_common.h" #include "s5p_mfc_ctrl.h" #include "s5p_mfc_debug.h" @@ -181,13 +181,6 @@ unlock: mutex_unlock(&dev->mfc_mutex); } -static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev) -{ - mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT); - mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD); - mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID); -} - static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_buf *dst_buf; @@ -199,22 +192,23 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx) dst_buf = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); mfc_debug(2, "Cleaning up buffer: %d\n", - dst_buf->b->v4l2_buf.index); - vb2_set_plane_payload(dst_buf->b, 0, 0); - vb2_set_plane_payload(dst_buf->b, 1, 0); + dst_buf->b->vb2_buf.index); + vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0, 0); + vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1, 0); list_del(&dst_buf->list); + dst_buf->flags |= MFC_BUF_FLAG_EOS; ctx->dst_queue_cnt--; - dst_buf->b->v4l2_buf.sequence = (ctx->sequence++); + dst_buf->b->sequence = (ctx->sequence++); if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) == s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx)) - dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE; + dst_buf->b->field = V4L2_FIELD_NONE; else - dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED; - dst_buf->b->v4l2_buf.flags |= V4L2_BUF_FLAG_LAST; + dst_buf->b->field = V4L2_FIELD_INTERLACED; + dst_buf->b->flags |= V4L2_BUF_FLAG_LAST; - ctx->dec_dst_flag &= ~(1 << dst_buf->b->v4l2_buf.index); - vb2_buffer_done(dst_buf->b, VB2_BUF_STATE_DONE); + ctx->dec_dst_flag &= ~(1 << dst_buf->b->vb2_buf.index); + vb2_buffer_done(&dst_buf->b->vb2_buf, VB2_BUF_STATE_DONE); } } @@ -235,27 +229,28 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx) appropriate flags. */ src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); list_for_each_entry(dst_buf, &ctx->dst_queue, list) { - if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) { - dst_buf->b->v4l2_buf.timecode = - src_buf->b->v4l2_buf.timecode; - dst_buf->b->v4l2_buf.timestamp = - src_buf->b->v4l2_buf.timestamp; - dst_buf->b->v4l2_buf.flags &= + if (vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0) + == dec_y_addr) { + dst_buf->b->timecode = + src_buf->b->timecode; + dst_buf->b->timestamp = + src_buf->b->timestamp; + dst_buf->b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_buf->b->v4l2_buf.flags |= - src_buf->b->v4l2_buf.flags + dst_buf->b->flags |= + src_buf->b->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; switch (frame_type) { case S5P_FIMV_DECODE_FRAME_I_FRAME: - dst_buf->b->v4l2_buf.flags |= + dst_buf->b->flags |= V4L2_BUF_FLAG_KEYFRAME; break; case S5P_FIMV_DECODE_FRAME_P_FRAME: - dst_buf->b->v4l2_buf.flags |= + dst_buf->b->flags |= V4L2_BUF_FLAG_PFRAME; break; case S5P_FIMV_DECODE_FRAME_B_FRAME: - dst_buf->b->v4l2_buf.flags |= + dst_buf->b->flags |= V4L2_BUF_FLAG_BFRAME; break; default: @@ -296,25 +291,28 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) * check which videobuf does it correspond to */ list_for_each_entry(dst_buf, &ctx->dst_queue, list) { /* Check if this is the buffer we're looking for */ - if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dspl_y_addr) { + if (vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0) + == dspl_y_addr) { list_del(&dst_buf->list); ctx->dst_queue_cnt--; - dst_buf->b->v4l2_buf.sequence = ctx->sequence; + dst_buf->b->sequence = ctx->sequence; if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) == s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx)) - dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE; + dst_buf->b->field = V4L2_FIELD_NONE; else - dst_buf->b->v4l2_buf.field = + dst_buf->b->field = V4L2_FIELD_INTERLACED; - vb2_set_plane_payload(dst_buf->b, 0, ctx->luma_size); - vb2_set_plane_payload(dst_buf->b, 1, ctx->chroma_size); - clear_bit(dst_buf->b->v4l2_buf.index, + vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0, + ctx->luma_size); + vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1, + ctx->chroma_size); + clear_bit(dst_buf->b->vb2_buf.index, &ctx->dec_dst_flag); - vb2_buffer_done(dst_buf->b, - err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); + vb2_buffer_done(&dst_buf->b->vb2_buf, err ? + VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); break; } @@ -395,7 +393,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC && ctx->codec_mode != S5P_MFC_CODEC_VP8_DEC && ctx->consumed_stream + STUFF_BYTE < - src_buf->b->v4l2_planes[0].bytesused) { + src_buf->b->vb2_buf.planes[0].bytesused) { /* Run MFC again on the same buffer */ mfc_debug(2, "Running again the same buffer\n"); ctx->after_packed_pb = 1; @@ -407,9 +405,11 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, list_del(&src_buf->list); ctx->src_queue_cnt--; if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0) - vb2_buffer_done(src_buf->b, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&src_buf->b->vb2_buf, + VB2_BUF_STATE_ERROR); else - vb2_buffer_done(src_buf->b, VB2_BUF_STATE_DONE); + vb2_buffer_done(&src_buf->b->vb2_buf, + VB2_BUF_STATE_DONE); } } leave_handle_frame: @@ -510,7 +510,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf, list); if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream, dev) < - src_buf->b->v4l2_planes[0].bytesused) + src_buf->b->vb2_buf.planes[0].bytesused) ctx->head_processed = 0; else ctx->head_processed = 1; @@ -551,7 +551,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf, list); list_del(&src_buf->list); ctx->src_queue_cnt--; - vb2_buffer_done(src_buf->b, + vb2_buffer_done(&src_buf->b->vb2_buf, VB2_BUF_STATE_DONE); } spin_unlock_irqrestore(&dev->irqlock, flags); @@ -573,17 +573,13 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, } } -static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, - unsigned int reason, unsigned int err) +static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *mb_entry; mfc_debug(2, "Stream completed\n"); - s5p_mfc_clear_int_flags(dev); - ctx->int_type = reason; - ctx->int_err = err; ctx->state = MFCINST_FINISHED; spin_lock(&dev->irqlock); @@ -592,8 +588,8 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, list); list_del(&mb_entry->list); ctx->dst_queue_cnt--; - vb2_set_plane_payload(mb_entry->b, 0, 0); - vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE); + 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); @@ -640,6 +636,13 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) if (ctx->c_ops->post_frame_start) { if (ctx->c_ops->post_frame_start(ctx)) mfc_err("post_frame_start() failed\n"); + + if (ctx->state == MFCINST_FINISHING && + list_empty(&ctx->ref_queue)) { + s5p_mfc_hw_call_void(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); wake_up_ctx(ctx, reason, err); WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); @@ -685,7 +688,10 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) break; case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET: - s5p_mfc_handle_stream_complete(ctx, reason, err); + s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev); + ctx->int_type = reason; + ctx->int_err = err; + s5p_mfc_handle_stream_complete(ctx); break; case S5P_MFC_R2H_CMD_DPB_FLUSH_RET: diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index 24262bbb1a35..d1a3f9b1bc44 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -21,7 +21,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include "regs-mfc.h" #include "regs-mfc-v8.h" @@ -179,8 +179,8 @@ struct s5p_mfc_ctx; * struct s5p_mfc_buf - MFC buffer */ struct s5p_mfc_buf { + struct vb2_v4l2_buffer *b; struct list_head list; - struct vb2_buffer *b; union { struct { size_t luma; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index aebe4fd7f03a..8c5060a7534f 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -22,7 +22,7 @@ #include <linux/workqueue.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include "s5p_mfc_common.h" #include "s5p_mfc_ctrl.h" #include "s5p_mfc_debug.h" @@ -645,17 +645,22 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) mfc_err("Call on DQBUF after unrecoverable error\n"); return -EIO; } - if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); - else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + + switch (buf->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK); - if (ret == 0 && ctx->state == MFCINST_FINISHED && - list_empty(&ctx->vq_dst.done_list)) + if (ret) + return ret; + + if (ctx->state == MFCINST_FINISHED && + (ctx->dst_bufs[buf->index].flags & MFC_BUF_FLAG_EOS)) v4l2_event_queue_fh(&ctx->fh, &ev); - } else { - ret = -EINVAL; + return 0; + default: + return -EINVAL; } - return ret; } /* Export DMA buffer */ @@ -883,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 struct v4l2_format *fmt, unsigned int *buf_count, + const void *parg, unsigned int *buf_count, unsigned int *plane_count, unsigned int psize[], void *allocators[]) { @@ -945,6 +950,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, static int s5p_mfc_buf_init(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); unsigned int i; @@ -964,8 +970,8 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) mfc_err("Plane buffer (CAPTURE) is too small\n"); return -EINVAL; } - i = vb->v4l2_buf.index; - ctx->dst_bufs[i].b = vb; + i = vb->index; + ctx->dst_bufs[i].b = vbuf; ctx->dst_bufs[i].cookie.raw.luma = vb2_dma_contig_plane_dma_addr(vb, 0); ctx->dst_bufs[i].cookie.raw.chroma = @@ -982,8 +988,8 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) return -EINVAL; } - i = vb->v4l2_buf.index; - ctx->src_bufs[i].b = vb; + i = vb->index; + ctx->src_bufs[i].b = vbuf; ctx->src_bufs[i].cookie.stream = vb2_dma_contig_plane_dma_addr(vb, 0); ctx->src_bufs_cnt++; @@ -1065,18 +1071,18 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) struct s5p_mfc_buf *mfc_buf; if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index]; + mfc_buf = &ctx->src_bufs[vb->index]; mfc_buf->flags &= ~MFC_BUF_FLAG_USED; spin_lock_irqsave(&dev->irqlock, flags); list_add_tail(&mfc_buf->list, &ctx->src_queue); ctx->src_queue_cnt++; spin_unlock_irqrestore(&dev->irqlock, flags); } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index]; + mfc_buf = &ctx->dst_bufs[vb->index]; mfc_buf->flags &= ~MFC_BUF_FLAG_USED; /* Mark destination as available for use by MFC */ spin_lock_irqsave(&dev->irqlock, flags); - set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag); + set_bit(vb->index, &ctx->dec_dst_flag); list_add_tail(&mfc_buf->list, &ctx->dst_queue); ctx->dst_queue_cnt++; spin_unlock_irqrestore(&dev->irqlock, flags); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 2e57e9f45b85..5c678ec9c9f2 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -23,7 +23,7 @@ #include <media/v4l2-event.h> #include <linux/workqueue.h> #include <media/v4l2-ctrls.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include "s5p_mfc_common.h" #include "s5p_mfc_ctrl.h" #include "s5p_mfc_debug.h" @@ -773,8 +773,8 @@ static int enc_pre_seq_start(struct s5p_mfc_ctx *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, 0); - dst_size = vb2_plane_size(dst_mb->b, 0); + 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, dst_size); spin_unlock_irqrestore(&dev->irqlock, flags); @@ -796,10 +796,11 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) struct s5p_mfc_buf, list); list_del(&dst_mb->list); ctx->dst_queue_cnt--; - vb2_set_plane_payload(dst_mb->b, 0, + vb2_set_plane_payload(&dst_mb->b->vb2_buf, 0, s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev)); - vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE); + vb2_buffer_done(&dst_mb->b->vb2_buf, + VB2_BUF_STATE_DONE); } spin_unlock_irqrestore(&dev->irqlock, flags); } @@ -831,16 +832,16 @@ static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx) 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, 0); - src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); + 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, 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, 0); - dst_size = vb2_plane_size(dst_mb->b, 0); + 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, dst_size); spin_unlock_irqrestore(&dev->irqlock, flags); @@ -869,25 +870,29 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) s5p_mfc_hw_call_void(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(mb_entry->b, 0); - mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1); + mb_y_addr = vb2_dma_contig_plane_dma_addr( + &mb_entry->b->vb2_buf, 0); + mb_c_addr = vb2_dma_contig_plane_dma_addr( + &mb_entry->b->vb2_buf, 1); if ((enc_y_addr == mb_y_addr) && (enc_c_addr == mb_c_addr)) { list_del(&mb_entry->list); ctx->src_queue_cnt--; - vb2_buffer_done(mb_entry->b, + vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE); break; } } list_for_each_entry(mb_entry, &ctx->ref_queue, list) { - mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0); - mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1); + mb_y_addr = vb2_dma_contig_plane_dma_addr( + &mb_entry->b->vb2_buf, 0); + mb_c_addr = vb2_dma_contig_plane_dma_addr( + &mb_entry->b->vb2_buf, 1); if ((enc_y_addr == mb_y_addr) && (enc_c_addr == mb_c_addr)) { list_del(&mb_entry->list); ctx->ref_queue_cnt--; - vb2_buffer_done(mb_entry->b, + vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE); break; } @@ -902,9 +907,9 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) list_add_tail(&mb_entry->list, &ctx->ref_queue); ctx->ref_queue_cnt++; } - mfc_debug(2, "enc src count: %d, enc ref count: %d\n", - ctx->src_queue_cnt, ctx->ref_queue_cnt); } + mfc_debug(2, "enc src count: %d, enc ref count: %d\n", + ctx->src_queue_cnt, ctx->ref_queue_cnt); if ((ctx->dst_queue_cnt > 0) && (strm_size > 0)) { mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); @@ -912,21 +917,22 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) ctx->dst_queue_cnt--; switch (slice_type) { case S5P_FIMV_ENC_SI_SLICE_TYPE_I: - mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; + mb_entry->b->flags |= V4L2_BUF_FLAG_KEYFRAME; break; case S5P_FIMV_ENC_SI_SLICE_TYPE_P: - mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; + mb_entry->b->flags |= V4L2_BUF_FLAG_PFRAME; break; case S5P_FIMV_ENC_SI_SLICE_TYPE_B: - mb_entry->b->v4l2_buf.flags |= V4L2_BUF_FLAG_BFRAME; + mb_entry->b->flags |= V4L2_BUF_FLAG_BFRAME; break; } - vb2_set_plane_payload(mb_entry->b, 0, strm_size); - vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE); + 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; } @@ -1806,13 +1812,13 @@ static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb) return -EINVAL; } mfc_debug(2, "index: %d, plane[%d] cookie: %pad\n", - vb->v4l2_buf.index, i, &dma); + vb->index, i, &dma); } return 0; } static int s5p_mfc_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + const void *parg, unsigned int *buf_count, unsigned int *plane_count, unsigned int psize[], void *allocators[]) { @@ -1821,7 +1827,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (ctx->state != MFCINST_GOT_INST) { - mfc_err("inavlid state: %d\n", ctx->state); + mfc_err("invalid state: %d\n", ctx->state); return -EINVAL; } @@ -1861,7 +1867,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX]; } } else { - mfc_err("inavlid queue type: %d\n", vq->type); + mfc_err("invalid queue type: %d\n", vq->type); return -EINVAL; } return 0; @@ -1869,6 +1875,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, static int s5p_mfc_buf_init(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); unsigned int i; @@ -1878,8 +1885,8 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) ret = check_vb_with_fmt(ctx->dst_fmt, vb); if (ret < 0) return ret; - i = vb->v4l2_buf.index; - ctx->dst_bufs[i].b = vb; + i = vb->index; + ctx->dst_bufs[i].b = vbuf; ctx->dst_bufs[i].cookie.stream = vb2_dma_contig_plane_dma_addr(vb, 0); ctx->dst_bufs_cnt++; @@ -1887,15 +1894,15 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) ret = check_vb_with_fmt(ctx->src_fmt, vb); if (ret < 0) return ret; - i = vb->v4l2_buf.index; - ctx->src_bufs[i].b = vb; + i = vb->index; + ctx->src_bufs[i].b = vbuf; ctx->src_bufs[i].cookie.raw.luma = vb2_dma_contig_plane_dma_addr(vb, 0); ctx->src_bufs[i].cookie.raw.chroma = vb2_dma_contig_plane_dma_addr(vb, 1); ctx->src_bufs_cnt++; } else { - mfc_err("inavlid queue type: %d\n", vq->type); + mfc_err("invalid queue type: %d\n", vq->type); return -EINVAL; } return 0; @@ -1931,7 +1938,7 @@ static int s5p_mfc_buf_prepare(struct vb2_buffer *vb) return -EINVAL; } } else { - mfc_err("inavlid queue type: %d\n", vq->type); + mfc_err("invalid queue type: %d\n", vq->type); return -EINVAL; } return 0; @@ -2012,7 +2019,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) return; } if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index]; + mfc_buf = &ctx->dst_bufs[vb->index]; mfc_buf->flags &= ~MFC_BUF_FLAG_USED; /* Mark destination as available for use by MFC */ spin_lock_irqsave(&dev->irqlock, flags); @@ -2020,7 +2027,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) ctx->dst_queue_cnt++; spin_unlock_irqrestore(&dev->irqlock, flags); } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index]; + mfc_buf = &ctx->src_bufs[vb->index]; mfc_buf->flags &= ~MFC_BUF_FLAG_USED; spin_lock_irqsave(&dev->irqlock, flags); list_add_tail(&mfc_buf->list, &ctx->src_queue); 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 6402f76cc620..873c933bc7d4 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -1208,11 +1208,11 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); temp_vb->flags |= MFC_BUF_FLAG_USED; s5p_mfc_set_dec_stream_buffer_v5(ctx, - vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), - ctx->consumed_stream, temp_vb->b->v4l2_planes[0].bytesused); + 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->v4l2_planes[0].bytesused == 0) { + if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) { last_frame = MFC_DEC_LAST_FRAME; mfc_debug(2, "Setting ctx->state to FINISHING\n"); ctx->state = MFCINST_FINISHING; @@ -1249,16 +1249,16 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); src_mb->flags |= MFC_BUF_FLAG_USED; - if (src_mb->b->v4l2_planes[0].bytesused == 0) { + if (src_mb->b->vb2_buf.planes[0].bytesused == 0) { /* send null frame */ s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2, dev->bank2); ctx->state = MFCINST_FINISHING; } else { - src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, - 0); - src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, - 1); + 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_set_enc_frame_buffer_v5(ctx, src_y_addr, src_c_addr); if (src_mb->flags & MFC_BUF_FLAG_EOS) @@ -1267,13 +1267,13 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) } dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); dst_mb->flags |= MFC_BUF_FLAG_USED; - dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); - dst_size = vb2_plane_size(dst_mb->b, 0); + 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->v4l2_buf.index : -1, ctx->state); + src_mb ? src_mb->b->vb2_buf.index : -1, ctx->state); s5p_mfc_encode_one_frame_v5(ctx); return 0; } @@ -1289,10 +1289,11 @@ static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) 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); - mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused); + mfc_debug(2, "Header size: %d\n", + temp_vb->b->vb2_buf.planes[0].bytesused); s5p_mfc_set_dec_stream_buffer_v5(ctx, - vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), - 0, temp_vb->b->v4l2_planes[0].bytesused); + 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); @@ -1309,8 +1310,8 @@ static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx) 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, 0); - dst_size = vb2_plane_size(dst_mb->b, 0); + 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; @@ -1342,10 +1343,11 @@ static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx) return -EIO; } temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); - mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused); + mfc_debug(2, "Header size: %d\n", + temp_vb->b->vb2_buf.planes[0].bytesused); s5p_mfc_set_dec_stream_buffer_v5(ctx, - vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), - 0, temp_vb->b->v4l2_planes[0].bytesused); + 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); @@ -1478,9 +1480,9 @@ static void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq) while (!list_empty(lh)) { b = list_entry(lh->next, struct s5p_mfc_buf, list); - for (i = 0; i < b->b->num_planes; i++) - vb2_set_plane_payload(b->b, i, 0); - vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR); + 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); } } 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 e5cb30e1f718..b95845347348 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -522,7 +522,7 @@ static int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx, writel(addr, mfc_regs->e_stream_buffer_addr); /* 16B align */ writel(size, mfc_regs->e_stream_buffer_size); - mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d\n", + mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%x\n", addr, size); return 0; @@ -554,7 +554,7 @@ static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, enc_recon_y_addr = readl(mfc_regs->e_recon_luma_dpb_addr); enc_recon_c_addr = readl(mfc_regs->e_recon_chroma_dpb_addr); - mfc_debug(2, "recon y addr: 0x%08lx\n", enc_recon_y_addr); + mfc_debug(2, "recon y addr: 0x%08lx y_addr: 0x%08lx\n", enc_recon_y_addr, *y_addr); mfc_debug(2, "recon c addr: 0x%08lx\n", enc_recon_c_addr); } @@ -1483,6 +1483,7 @@ static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; + int cmd; mfc_debug(2, "++\n"); @@ -1493,9 +1494,13 @@ static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx) s5p_mfc_set_slice_mode(ctx); + if (ctx->state != MFCINST_FINISHING) + cmd = S5P_FIMV_CH_FRAME_START_V6; + else + 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, - S5P_FIMV_CH_FRAME_START_V6, NULL); + s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, cmd, NULL); mfc_debug(2, "--\n"); @@ -1562,13 +1567,13 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); temp_vb->flags |= MFC_BUF_FLAG_USED; s5p_mfc_set_dec_stream_buffer_v6(ctx, - vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), + vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0), ctx->consumed_stream, - temp_vb->b->v4l2_planes[0].bytesused); + temp_vb->b->vb2_buf.planes[0].bytesused); spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; - if (temp_vb->b->v4l2_planes[0].bytesused == 0) { + if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) { last_frame = 1; mfc_debug(2, "Setting ctx->state to FINISHING\n"); ctx->state = MFCINST_FINISHING; @@ -1592,7 +1597,7 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) spin_lock_irqsave(&dev->irqlock, flags); - if (list_empty(&ctx->src_queue)) { + 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; @@ -1604,20 +1609,33 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) return -EAGAIN; } - src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); - src_mb->flags |= MFC_BUF_FLAG_USED; - src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0); - src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); + if (list_empty(&ctx->src_queue)) { + /* send null frame */ + s5p_mfc_set_enc_frame_buffer_v6(ctx, 0, 0); + src_mb = NULL; + } else { + src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); + src_mb->flags |= MFC_BUF_FLAG_USED; + if (src_mb->b->vb2_buf.planes[0].bytesused == 0) { + s5p_mfc_set_enc_frame_buffer_v6(ctx, 0, 0); + ctx->state = MFCINST_FINISHING; + } else { + 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); - mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr); - mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr); + mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr); + mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr); - s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr); + s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr); + if (src_mb->flags & MFC_BUF_FLAG_EOS) + ctx->state = MFCINST_FINISHING; + } + } dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); dst_mb->flags |= MFC_BUF_FLAG_USED; - dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); - dst_size = vb2_plane_size(dst_mb->b, 0); + 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); @@ -1639,10 +1657,10 @@ static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) 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->v4l2_planes[0].bytesused); + 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, 0), 0, - temp_vb->b->v4l2_planes[0].bytesused); + 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); @@ -1659,8 +1677,8 @@ static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *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, 0); - dst_size = vb2_plane_size(dst_mb->b, 0); + 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; @@ -1836,9 +1854,9 @@ static void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq) while (!list_empty(lh)) { b = list_entry(lh->next, struct s5p_mfc_buf, list); - for (i = 0; i < b->b->num_planes; i++) - vb2_set_plane_payload(b->b, i, 0); - vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR); + 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); } } diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h index fb2acc53112a..42cd2709c41c 100644 --- a/drivers/media/platform/s5p-tv/mixer.h +++ b/drivers/media/platform/s5p-tv/mixer.h @@ -24,7 +24,7 @@ #include <linux/spinlock.h> #include <linux/wait.h> #include <media/v4l2-device.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include "regs-mixer.h" @@ -113,7 +113,7 @@ struct mxr_geometry { /** instance of a buffer */ struct mxr_buffer { /** common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; /** node for layer's lists */ struct list_head list; }; diff --git a/drivers/media/platform/s5p-tv/mixer_grp_layer.c b/drivers/media/platform/s5p-tv/mixer_grp_layer.c index 74344c764daa..db3163b23ea0 100644 --- a/drivers/media/platform/s5p-tv/mixer_grp_layer.c +++ b/drivers/media/platform/s5p-tv/mixer_grp_layer.c @@ -86,7 +86,7 @@ static void mxr_graph_buffer_set(struct mxr_layer *layer, dma_addr_t addr = 0; if (buf) - addr = vb2_dma_contig_plane_dma_addr(&buf->vb, 0); + addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); mxr_reg_graph_buffer(layer->mdev, layer->idx, addr); } diff --git a/drivers/media/platform/s5p-tv/mixer_reg.c b/drivers/media/platform/s5p-tv/mixer_reg.c index 5127acb1e571..a0ec14a1da13 100644 --- a/drivers/media/platform/s5p-tv/mixer_reg.c +++ b/drivers/media/platform/s5p-tv/mixer_reg.c @@ -279,7 +279,7 @@ static void mxr_irq_layer_handle(struct mxr_layer *layer) layer->ops.buffer_set(layer, layer->update_buf); if (done && done != layer->shadow_buf) - vb2_buffer_done(&done->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&done->vb.vb2_buf, VB2_BUF_STATE_DONE); done: spin_unlock(&layer->enq_slock); diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index 751f3b618337..dc1c679e136c 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 struct v4l2_format *pfmt, +static int queue_setup(struct vb2_queue *vq, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -914,7 +914,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt, static void buf_queue(struct vb2_buffer *vb) { - struct mxr_buffer *buffer = container_of(vb, struct mxr_buffer, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct mxr_buffer *buffer = container_of(vbuf, struct mxr_buffer, vb); struct mxr_layer *layer = vb2_get_drv_priv(vb->vb2_queue); struct mxr_device *mdev = layer->mdev; unsigned long flags; @@ -963,11 +964,13 @@ static void mxr_watchdog(unsigned long arg) if (layer->update_buf == layer->shadow_buf) layer->update_buf = NULL; if (layer->update_buf) { - vb2_buffer_done(&layer->update_buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&layer->update_buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); layer->update_buf = NULL; } if (layer->shadow_buf) { - vb2_buffer_done(&layer->shadow_buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&layer->shadow_buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); layer->shadow_buf = NULL; } spin_unlock_irqrestore(&layer->enq_slock, flags); @@ -991,7 +994,7 @@ static void stop_streaming(struct vb2_queue *vq) /* set all buffer to be done */ list_for_each_entry_safe(buf, buf_tmp, &layer->enq_list, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&layer->enq_slock, flags); diff --git a/drivers/media/platform/s5p-tv/mixer_vp_layer.c b/drivers/media/platform/s5p-tv/mixer_vp_layer.c index c9388c45ad75..dd002a497dbb 100644 --- a/drivers/media/platform/s5p-tv/mixer_vp_layer.c +++ b/drivers/media/platform/s5p-tv/mixer_vp_layer.c @@ -97,9 +97,10 @@ static void mxr_vp_buffer_set(struct mxr_layer *layer, mxr_reg_vp_buffer(layer->mdev, luma_addr, chroma_addr); return; } - luma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb, 0); + luma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); if (layer->fmt->num_subframes == 2) { - chroma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb, 1); + chroma_addr[0] = + vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 1); } else { /* FIXME: mxr_get_plane_size compute integer division, * which is slow and should not be performed in interrupt */ diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index f5e3eb3a20ff..d6ab33e7060a 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -865,10 +865,11 @@ static const struct v4l2_ioctl_ops sh_veu_ioctl_ops = { /* ========== Queue operations ========== */ static int sh_veu_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *f, + 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; @@ -931,9 +932,10 @@ static int sh_veu_buf_prepare(struct vb2_buffer *vb) static void sh_veu_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue); - dev_dbg(veu->dev, "%s(%d)\n", __func__, vb->v4l2_buf.type); - v4l2_m2m_buf_queue(veu->m2m_ctx, vb); + dev_dbg(veu->dev, "%s(%d)\n", __func__, vb->type); + v4l2_m2m_buf_queue(veu->m2m_ctx, vbuf); } static const struct vb2_ops sh_veu_qops = { @@ -1084,8 +1086,8 @@ static irqreturn_t sh_veu_bh(int irq, void *dev_id) static irqreturn_t sh_veu_isr(int irq, void *dev_id) { struct sh_veu_dev *veu = dev_id; - struct vb2_buffer *dst; - struct vb2_buffer *src; + struct vb2_v4l2_buffer *dst; + struct vb2_v4l2_buffer *src; u32 status = sh_veu_reg_read(veu, VEU_EVTR); /* bundle read mode not used */ @@ -1105,11 +1107,11 @@ static irqreturn_t sh_veu_isr(int irq, void *dev_id) if (!src || !dst) return IRQ_NONE; - dst->v4l2_buf.timestamp = src->v4l2_buf.timestamp; - dst->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst->v4l2_buf.flags |= - src->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst->v4l2_buf.timecode = src->v4l2_buf.timecode; + dst->timestamp = src->timestamp; + dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst->flags |= + src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst->timecode = src->timecode; spin_lock(&veu->lock); v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index fe5c8ab06bd5..2231f8922df3 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -27,6 +27,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-mediabus.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> /* Mirror addresses are not available for all registers */ @@ -62,11 +63,12 @@ enum sh_vou_status { #define VOU_MIN_IMAGE_HEIGHT 16 struct sh_vou_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; -static inline struct sh_vou_buffer *to_sh_vou_buffer(struct vb2_buffer *vb2) +static inline struct +sh_vou_buffer *to_sh_vou_buffer(struct vb2_v4l2_buffer *vb2) { return container_of(vb2, struct sh_vou_buffer, vb); } @@ -193,11 +195,11 @@ static struct sh_vou_fmt vou_fmt[] = { }; static void sh_vou_schedule_next(struct sh_vou_device *vou_dev, - struct vb2_buffer *vb) + struct vb2_v4l2_buffer *vbuf) { dma_addr_t addr1, addr2; - addr1 = vb2_dma_contig_plane_dma_addr(vb, 0); + addr1 = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); switch (vou_dev->pix.pixelformat) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV16: @@ -241,10 +243,11 @@ 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 struct v4l2_format *fmt, +static int sh_vou_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 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; @@ -282,8 +285,9 @@ static int sh_vou_buf_prepare(struct vb2_buffer *vb) /* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */ static void sh_vou_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct sh_vou_device *vou_dev = vb2_get_drv_priv(vb->vb2_queue); - struct sh_vou_buffer *shbuf = to_sh_vou_buffer(vb); + struct sh_vou_buffer *shbuf = to_sh_vou_buffer(vbuf); unsigned long flags; spin_lock_irqsave(&vou_dev->lock, flags); @@ -302,7 +306,8 @@ static int sh_vou_start_streaming(struct vb2_queue *vq, unsigned int count) video, s_stream, 1); if (ret < 0 && ret != -ENOIOCTLCMD) { list_for_each_entry_safe(buf, node, &vou_dev->buf_list, list) { - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_QUEUED); list_del(&buf->list); } vou_dev->active = NULL; @@ -353,7 +358,7 @@ static void sh_vou_stop_streaming(struct vb2_queue *vq) msleep(50); spin_lock_irqsave(&vou_dev->lock, flags); list_for_each_entry_safe(buf, node, &vou_dev->buf_list, list) { - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); list_del(&buf->list); } vou_dev->active = NULL; @@ -1066,10 +1071,10 @@ static irqreturn_t sh_vou_isr(int irq, void *dev_id) list_del(&vb->list); - v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp); - vb->vb.v4l2_buf.sequence = vou_dev->sequence++; - vb->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; - vb2_buffer_done(&vb->vb, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&vb->vb.timestamp); + vb->vb.sequence = vou_dev->sequence++; + vb->vb.field = V4L2_FIELD_INTERLACED; + vb2_buffer_done(&vb->vb.vb2_buf, VB2_BUF_STATE_DONE); vou_dev->active = list_entry(vou_dev->buf_list.next, struct sh_vou_buffer, list); diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index 90701726a06a..454f68f0cdad 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c @@ -23,12 +23,13 @@ #include <linux/pm_runtime.h> #include <linux/slab.h> -#include <media/atmel-isi.h> #include <media/soc_camera.h> #include <media/soc_mediabus.h> #include <media/v4l2-of.h> #include <media/videobuf2-dma-contig.h> +#include "atmel-isi.h" + #define MAX_BUFFER_NUM 32 #define MAX_SUPPORT_WIDTH 2048 #define MAX_SUPPORT_HEIGHT 2048 @@ -59,7 +60,7 @@ struct isi_dma_desc { /* Frame buffer data */ struct frame_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct isi_dma_desc *p_dma_desc; struct list_head list; }; @@ -102,62 +103,71 @@ static u32 isi_readl(struct atmel_isi *isi, u32 reg) return readl(isi->regs + reg); } -static int configure_geometry(struct atmel_isi *isi, u32 width, +static void configure_geometry(struct atmel_isi *isi, u32 width, u32 height, u32 code) { - u32 cfg2, cr; + u32 cfg2; + /* According to sensor's output format to set cfg2 */ switch (code) { - /* YUV, including grey */ + default: + /* Grey */ case MEDIA_BUS_FMT_Y8_1X8: - cr = ISI_CFG2_GRAYSCALE; + cfg2 = ISI_CFG2_GRAYSCALE | ISI_CFG2_COL_SPACE_YCbCr; break; + /* YUV */ case MEDIA_BUS_FMT_VYUY8_2X8: - cr = ISI_CFG2_YCC_SWAP_MODE_3; + cfg2 = ISI_CFG2_YCC_SWAP_MODE_3 | ISI_CFG2_COL_SPACE_YCbCr; break; case MEDIA_BUS_FMT_UYVY8_2X8: - cr = ISI_CFG2_YCC_SWAP_MODE_2; + cfg2 = ISI_CFG2_YCC_SWAP_MODE_2 | ISI_CFG2_COL_SPACE_YCbCr; break; case MEDIA_BUS_FMT_YVYU8_2X8: - cr = ISI_CFG2_YCC_SWAP_MODE_1; + cfg2 = ISI_CFG2_YCC_SWAP_MODE_1 | ISI_CFG2_COL_SPACE_YCbCr; break; case MEDIA_BUS_FMT_YUYV8_2X8: - cr = ISI_CFG2_YCC_SWAP_DEFAULT; + cfg2 = ISI_CFG2_YCC_SWAP_DEFAULT | ISI_CFG2_COL_SPACE_YCbCr; break; /* RGB, TODO */ - default: - return -EINVAL; } isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); - - cfg2 = isi_readl(isi, ISI_CFG2); - /* Set YCC swap mode */ - cfg2 &= ~ISI_CFG2_YCC_SWAP_MODE_MASK; - cfg2 |= cr; /* Set width */ - cfg2 &= ~(ISI_CFG2_IM_HSIZE_MASK); cfg2 |= ((width - 1) << ISI_CFG2_IM_HSIZE_OFFSET) & ISI_CFG2_IM_HSIZE_MASK; /* Set height */ - cfg2 &= ~(ISI_CFG2_IM_VSIZE_MASK); cfg2 |= ((height - 1) << ISI_CFG2_IM_VSIZE_OFFSET) & ISI_CFG2_IM_VSIZE_MASK; isi_writel(isi, ISI_CFG2, cfg2); +} - return 0; +static bool is_supported(struct soc_camera_device *icd, + const u32 pixformat) +{ + switch (pixformat) { + /* YUV, including grey */ + case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_VYUY: + return true; + /* RGB, TODO */ + default: + return false; + } } static irqreturn_t atmel_isi_handle_streaming(struct atmel_isi *isi) { if (isi->active) { - struct vb2_buffer *vb = &isi->active->vb; + struct vb2_v4l2_buffer *vbuf = &isi->active->vb; struct frame_buffer *buf = isi->active; list_del_init(&buf->list); - v4l2_get_timestamp(&vb->v4l2_buf.timestamp); - vb->v4l2_buf.sequence = isi->sequence++; - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&vbuf->timestamp); + vbuf->sequence = isi->sequence++; + vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); } if (list_empty(&isi->video_buffer_list)) { @@ -225,7 +235,7 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset) } timeout = wait_for_completion_timeout(&isi->complete, - msecs_to_jiffies(100)); + msecs_to_jiffies(500)); if (timeout == 0) return -ETIMEDOUT; @@ -235,7 +245,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 struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *vq, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -267,7 +277,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, static int buffer_init(struct vb2_buffer *vb) { - struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb); buf->p_dma_desc = NULL; INIT_LIST_HEAD(&buf->list); @@ -277,8 +288,9 @@ static int buffer_init(struct vb2_buffer *vb) static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); - struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb); + struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct atmel_isi *isi = ici->priv; unsigned long size; @@ -292,7 +304,7 @@ static int buffer_prepare(struct vb2_buffer *vb) return -EINVAL; } - vb2_set_plane_payload(&buf->vb, 0, size); + vb2_set_plane_payload(vb, 0, size); if (!buf->p_dma_desc) { if (list_empty(&isi->dma_desc_head)) { @@ -319,10 +331,11 @@ static int buffer_prepare(struct vb2_buffer *vb) static void buffer_cleanup(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct atmel_isi *isi = ici->priv; - struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb); + struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb); /* This descriptor is available now and we add to head list */ if (buf->p_dma_desc) @@ -360,10 +373,11 @@ static void start_dma(struct atmel_isi *isi, struct frame_buffer *buffer) static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct atmel_isi *isi = ici->priv; - struct frame_buffer *buf = container_of(vb, struct frame_buffer, vb); + struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb); unsigned long flags = 0; spin_lock_irqsave(&isi->lock, flags); @@ -396,6 +410,9 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) /* Disable all interrupts */ isi_writel(isi, ISI_INTDIS, (u32)~0UL); + configure_geometry(isi, icd->user_width, icd->user_height, + icd->current_fmt->code); + spin_lock_irq(&isi->lock); /* Clear any pending interrupt */ isi_readl(isi, ISI_STATUS); @@ -422,7 +439,7 @@ static void stop_streaming(struct vb2_queue *vq) /* Release all active buffers */ list_for_each_entry_safe(buf, node, &isi->video_buffer_list, list) { list_del_init(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irq(&isi->lock); @@ -483,8 +500,6 @@ static int isi_camera_init_videobuf(struct vb2_queue *q, static int isi_camera_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct atmel_isi *isi = ici->priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; @@ -494,6 +509,10 @@ static int isi_camera_set_fmt(struct soc_camera_device *icd, struct v4l2_mbus_framefmt *mf = &format.format; int ret; + /* check with atmel-isi support format, if not support use YUYV */ + if (!is_supported(icd, pix->pixelformat)) + pix->pixelformat = V4L2_PIX_FMT_YUYV; + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { dev_warn(icd->parent, "Format %x not found\n", @@ -517,16 +536,6 @@ static int isi_camera_set_fmt(struct soc_camera_device *icd, if (mf->code != xlate->code) return -EINVAL; - /* Enable PM and peripheral clock before operate isi registers */ - pm_runtime_get_sync(ici->v4l2_dev.dev); - - ret = configure_geometry(isi, pix->width, pix->height, xlate->code); - - pm_runtime_put(ici->v4l2_dev.dev); - - if (ret < 0) - return ret; - pix->width = mf->width; pix->height = mf->height; pix->field = mf->field; @@ -553,6 +562,10 @@ static int isi_camera_try_fmt(struct soc_camera_device *icd, u32 pixfmt = pix->pixelformat; int ret; + /* check with atmel-isi support format, if not support use YUYV */ + if (!is_supported(icd, pix->pixelformat)) + pix->pixelformat = V4L2_PIX_FMT_YUYV; + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (pixfmt && !xlate) { dev_warn(icd->parent, "Format %x not found\n", pixfmt); @@ -824,6 +837,11 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd) if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING; + dev_dbg(icd->parent, "vsync active %s, hsync active %s, sampling on pix clock %s edge\n", + common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? "low" : "high", + common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? "low" : "high", + common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING ? "falling" : "rising"); + if (isi->pdata.has_emb_sync) cfg1 |= ISI_CFG1_EMB_SYNC; if (isi->pdata.full_mode) @@ -873,7 +891,7 @@ static int atmel_isi_remove(struct platform_device *pdev) return 0; } -static int atmel_isi_probe_dt(struct atmel_isi *isi, +static int atmel_isi_parse_dt(struct atmel_isi *isi, struct platform_device *pdev) { struct device_node *np= pdev->dev.of_node; @@ -891,9 +909,10 @@ static int atmel_isi_probe_dt(struct atmel_isi *isi, } err = v4l2_of_parse_endpoint(np, &ep); + of_node_put(np); if (err) { dev_err(&pdev->dev, "Could not parse the endpoint\n"); - goto err_probe_dt; + return err; } switch (ep.bus.parallel.bus_width) { @@ -907,14 +926,20 @@ static int atmel_isi_probe_dt(struct atmel_isi *isi, default: dev_err(&pdev->dev, "Unsupported bus width: %d\n", ep.bus.parallel.bus_width); - err = -EINVAL; - goto err_probe_dt; + return -EINVAL; } -err_probe_dt: - of_node_put(np); + if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) + isi->pdata.hsync_act_low = true; + if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) + isi->pdata.vsync_act_low = true; + if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) + isi->pdata.pclk_act_falling = true; - return err; + if (ep.bus_type == V4L2_MBUS_BT656) + isi->pdata.has_emb_sync = true; + + return 0; } static int atmel_isi_probe(struct platform_device *pdev) @@ -923,16 +948,7 @@ static int atmel_isi_probe(struct platform_device *pdev) struct atmel_isi *isi; struct resource *regs; int ret, i; - struct device *dev = &pdev->dev; struct soc_camera_host *soc_host; - struct isi_platform_data *pdata; - - pdata = dev->platform_data; - if ((!pdata || !pdata->data_width_flags) && !pdev->dev.of_node) { - dev_err(&pdev->dev, - "No config available for Atmel ISI\n"); - return -EINVAL; - } isi = devm_kzalloc(&pdev->dev, sizeof(struct atmel_isi), GFP_KERNEL); if (!isi) { @@ -944,13 +960,9 @@ static int atmel_isi_probe(struct platform_device *pdev) if (IS_ERR(isi->pclk)) return PTR_ERR(isi->pclk); - if (pdata) { - memcpy(&isi->pdata, pdata, sizeof(isi->pdata)); - } else { - ret = atmel_isi_probe_dt(isi, pdev); - if (ret) - return ret; - } + ret = atmel_isi_parse_dt(isi, pdev); + if (ret) + return ret; isi->active = NULL; spin_lock_init(&isi->lock); @@ -1014,11 +1026,6 @@ static int atmel_isi_probe(struct platform_device *pdev) pm_suspend_ignore_children(&pdev->dev, true); pm_runtime_enable(&pdev->dev); - if (isi->pdata.asd_sizes) { - soc_host->asd = isi->pdata.asd; - soc_host->asd_sizes = isi->pdata.asd_sizes; - } - ret = soc_camera_host_register(soc_host); if (ret) { dev_err(&pdev->dev, "Unable to register soc camera host\n"); @@ -1040,6 +1047,7 @@ err_alloc_ctx: return ret; } +#ifdef CONFIG_PM static int atmel_isi_runtime_suspend(struct device *dev) { struct soc_camera_host *soc_host = to_soc_camera_host(dev); @@ -1058,6 +1066,7 @@ static int atmel_isi_runtime_resume(struct device *dev) return clk_prepare_enable(isi->pclk); } +#endif /* CONFIG_PM */ static const struct dev_pm_ops atmel_isi_dev_pm_ops = { SET_RUNTIME_PM_OPS(atmel_isi_runtime_suspend, diff --git a/drivers/media/platform/soc_camera/atmel-isi.h b/drivers/media/platform/soc_camera/atmel-isi.h new file mode 100644 index 000000000000..5acc771d2edc --- /dev/null +++ b/drivers/media/platform/soc_camera/atmel-isi.h @@ -0,0 +1,128 @@ +/* + * Register definitions for the Atmel Image Sensor Interface. + * + * Copyright (C) 2011 Atmel Corporation + * Josh Wu, <josh.wu@atmel.com> + * + * Based on previous work by Lars Haring, <lars.haring@atmel.com> + * and Sedji Gaouaou + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __ATMEL_ISI_H__ +#define __ATMEL_ISI_H__ + +#include <linux/types.h> + +/* ISI_V2 register offsets */ +#define ISI_CFG1 0x0000 +#define ISI_CFG2 0x0004 +#define ISI_PSIZE 0x0008 +#define ISI_PDECF 0x000c +#define ISI_Y2R_SET0 0x0010 +#define ISI_Y2R_SET1 0x0014 +#define ISI_R2Y_SET0 0x0018 +#define ISI_R2Y_SET1 0x001C +#define ISI_R2Y_SET2 0x0020 +#define ISI_CTRL 0x0024 +#define ISI_STATUS 0x0028 +#define ISI_INTEN 0x002C +#define ISI_INTDIS 0x0030 +#define ISI_INTMASK 0x0034 +#define ISI_DMA_CHER 0x0038 +#define ISI_DMA_CHDR 0x003C +#define ISI_DMA_CHSR 0x0040 +#define ISI_DMA_P_ADDR 0x0044 +#define ISI_DMA_P_CTRL 0x0048 +#define ISI_DMA_P_DSCR 0x004C +#define ISI_DMA_C_ADDR 0x0050 +#define ISI_DMA_C_CTRL 0x0054 +#define ISI_DMA_C_DSCR 0x0058 + +/* Bitfields in CFG1 */ +#define ISI_CFG1_HSYNC_POL_ACTIVE_LOW (1 << 2) +#define ISI_CFG1_VSYNC_POL_ACTIVE_LOW (1 << 3) +#define ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING (1 << 4) +#define ISI_CFG1_EMB_SYNC (1 << 6) +#define ISI_CFG1_CRC_SYNC (1 << 7) +/* Constants for FRATE(ISI_V2) */ +#define ISI_CFG1_FRATE_CAPTURE_ALL (0 << 8) +#define ISI_CFG1_FRATE_DIV_2 (1 << 8) +#define ISI_CFG1_FRATE_DIV_3 (2 << 8) +#define ISI_CFG1_FRATE_DIV_4 (3 << 8) +#define ISI_CFG1_FRATE_DIV_5 (4 << 8) +#define ISI_CFG1_FRATE_DIV_6 (5 << 8) +#define ISI_CFG1_FRATE_DIV_7 (6 << 8) +#define ISI_CFG1_FRATE_DIV_8 (7 << 8) +#define ISI_CFG1_FRATE_DIV_MASK (7 << 8) +#define ISI_CFG1_DISCR (1 << 11) +#define ISI_CFG1_FULL_MODE (1 << 12) +/* Definition for THMASK(ISI_V2) */ +#define ISI_CFG1_THMASK_BEATS_4 (0 << 13) +#define ISI_CFG1_THMASK_BEATS_8 (1 << 13) +#define ISI_CFG1_THMASK_BEATS_16 (2 << 13) + +/* Bitfields in CFG2 */ +#define ISI_CFG2_GRAYSCALE (1 << 13) +#define ISI_CFG2_COL_SPACE_YCbCr (0 << 15) +#define ISI_CFG2_COL_SPACE_RGB (1 << 15) +/* Constants for YCC_SWAP(ISI_V2) */ +#define ISI_CFG2_YCC_SWAP_DEFAULT (0 << 28) +#define ISI_CFG2_YCC_SWAP_MODE_1 (1 << 28) +#define ISI_CFG2_YCC_SWAP_MODE_2 (2 << 28) +#define ISI_CFG2_YCC_SWAP_MODE_3 (3 << 28) +#define ISI_CFG2_YCC_SWAP_MODE_MASK (3 << 28) +#define ISI_CFG2_IM_VSIZE_OFFSET 0 +#define ISI_CFG2_IM_HSIZE_OFFSET 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 CTRL */ +/* Also using in SR(ISI_V2) */ +#define ISI_CTRL_EN (1 << 0) +#define ISI_CTRL_CDC (1 << 8) +/* Also using in SR/IER/IDR/IMR(ISI_V2) */ +#define ISI_CTRL_DIS (1 << 1) +#define ISI_CTRL_SRST (1 << 2) + +/* Bitfields in SR */ +#define ISI_SR_SIP (1 << 19) +/* Also using in SR/IER/IDR/IMR */ +#define ISI_SR_VSYNC (1 << 10) +#define ISI_SR_PXFR_DONE (1 << 16) +#define ISI_SR_CXFR_DONE (1 << 17) +#define ISI_SR_P_OVR (1 << 24) +#define ISI_SR_C_OVR (1 << 25) +#define ISI_SR_CRC_ERR (1 << 26) +#define ISI_SR_FR_OVR (1 << 27) + +/* Bitfields in DMA_C_CTRL & in DMA_P_CTRL */ +#define ISI_DMA_CTRL_FETCH (1 << 0) +#define ISI_DMA_CTRL_WB (1 << 1) +#define ISI_DMA_CTRL_IEN (1 << 2) +#define ISI_DMA_CTRL_DONE (1 << 3) + +/* Bitfields in DMA_CHSR/CHER/CHDR */ +#define ISI_DMA_CHSR_P_CH (1 << 0) +#define ISI_DMA_CHSR_C_CH (1 << 1) + +/* Definition for isi_platform_data */ +#define ISI_DATAWIDTH_8 0x01 +#define ISI_DATAWIDTH_10 0x02 + +struct v4l2_async_subdev; + +struct isi_platform_data { + u8 has_emb_sync; + u8 hsync_act_low; + u8 vsync_act_low; + u8 pclk_act_falling; + u8 full_mode; + u32 data_width_flags; + /* Using for ISI_CFG1 */ + u32 frate; +}; + +#endif /* __ATMEL_ISI_H__ */ diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c index ea4c423f0cf8..1f28d21a3c9a 100644 --- a/drivers/media/platform/soc_camera/mx2_camera.c +++ b/drivers/media/platform/soc_camera/mx2_camera.c @@ -32,7 +32,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-dev.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include <media/soc_camera.h> #include <media/soc_mediabus.h> @@ -225,7 +225,7 @@ struct mx2_buf_internal { /* buffer for one video frame */ struct mx2_buffer { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct mx2_buf_internal internal; }; @@ -469,10 +469,11 @@ static void mx2_camera_clock_stop(struct soc_camera_host *ici) * Videobuf operations */ static int mx2_videobuf_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + 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; @@ -530,11 +531,12 @@ out: static void mx2_videobuf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx2_camera_dev *pcdev = ici->priv; - struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); + struct mx2_buffer *buf = container_of(vbuf, struct mx2_buffer, vb); unsigned long flags; dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, @@ -664,7 +666,7 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) buf = list_first_entry(&pcdev->capture, struct mx2_buffer, internal.queue); buf->internal.bufnum = 0; - vb = &buf->vb; + vb = &buf->vb.vb2_buf; phys = vb2_dma_contig_plane_dma_addr(vb, 0); mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); @@ -673,7 +675,7 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) buf = list_first_entry(&pcdev->capture, struct mx2_buffer, internal.queue); buf->internal.bufnum = 1; - vb = &buf->vb; + vb = &buf->vb.vb2_buf; phys = vb2_dma_contig_plane_dma_addr(vb, 0); mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); @@ -1307,6 +1309,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, struct mx2_buf_internal *ibuf; struct mx2_buffer *buf; struct vb2_buffer *vb; + struct vb2_v4l2_buffer *vbuf; unsigned long phys; ibuf = list_first_entry(&pcdev->active_bufs, struct mx2_buf_internal, @@ -1323,7 +1326,8 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, } else { buf = mx2_ibuf_to_buf(ibuf); - vb = &buf->vb; + vb = &buf->vb.vb2_buf; + vbuf = to_vb2_v4l2_buffer(vb); #ifdef DEBUG phys = vb2_dma_contig_plane_dma_addr(vb, 0); if (prp->cfg.channel == 1) { @@ -1347,8 +1351,8 @@ 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(&vb->v4l2_buf.timestamp); - vb->v4l2_buf.sequence = pcdev->frame_count; + v4l2_get_timestamp(&vbuf->timestamp); + vbuf->sequence = pcdev->frame_count; if (err) vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); else @@ -1380,7 +1384,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, list_move_tail(pcdev->capture.next, &pcdev->active_bufs); - vb = &buf->vb; + vb = &buf->vb.vb2_buf; phys = vb2_dma_contig_plane_dma_addr(vb, 0); mx27_update_emma_buf(pcdev, phys, bufnum); diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index ace41f53caca..49c3a257a916 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c @@ -63,7 +63,7 @@ struct mx3_camera_buffer { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head queue; /* One descriptot per scatterlist (per frame) */ @@ -133,7 +133,7 @@ static void csi_reg_write(struct mx3_camera_dev *mx3, u32 value, off_t reg) __raw_writel(value, mx3->base + reg); } -static struct mx3_camera_buffer *to_mx3_vb(struct vb2_buffer *vb) +static struct mx3_camera_buffer *to_mx3_vb(struct vb2_v4l2_buffer *vb) { return container_of(vb, struct mx3_camera_buffer, vb); } @@ -151,14 +151,14 @@ static void mx3_cam_dma_done(void *arg) spin_lock(&mx3_cam->lock); if (mx3_cam->active) { - struct vb2_buffer *vb = &mx3_cam->active->vb; + struct vb2_v4l2_buffer *vb = &mx3_cam->active->vb; struct mx3_camera_buffer *buf = to_mx3_vb(vb); list_del_init(&buf->queue); - v4l2_get_timestamp(&vb->v4l2_buf.timestamp); - vb->v4l2_buf.field = mx3_cam->field; - vb->v4l2_buf.sequence = mx3_cam->sequence++; - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + v4l2_get_timestamp(&vb->timestamp); + vb->field = mx3_cam->field; + vb->sequence = mx3_cam->sequence++; + vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE); } if (list_empty(&mx3_cam->capture)) { @@ -185,10 +185,11 @@ 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 struct v4l2_format *fmt, + 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; @@ -257,10 +258,11 @@ static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) static void mx3_videobuf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx3_camera_dev *mx3_cam = ici->priv; - struct mx3_camera_buffer *buf = to_mx3_vb(vb); + struct mx3_camera_buffer *buf = to_mx3_vb(vbuf); struct scatterlist *sg = &buf->sg; struct dma_async_tx_descriptor *txd; struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; @@ -273,7 +275,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb) if (vb2_plane_size(vb, 0) < new_size) { dev_err(icd->parent, "Buffer #%d too small (%lu < %zu)\n", - vb->v4l2_buf.index, vb2_plane_size(vb, 0), new_size); + vbuf->vb2_buf.index, vb2_plane_size(vb, 0), new_size); goto error; } @@ -357,10 +359,11 @@ error: static void mx3_videobuf_release(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx3_camera_dev *mx3_cam = ici->priv; - struct mx3_camera_buffer *buf = to_mx3_vb(vb); + struct mx3_camera_buffer *buf = to_mx3_vb(vbuf); struct dma_async_tx_descriptor *txd = buf->txd; unsigned long flags; @@ -390,10 +393,11 @@ static void mx3_videobuf_release(struct vb2_buffer *vb) static int mx3_videobuf_init(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx3_camera_dev *mx3_cam = ici->priv; - struct mx3_camera_buffer *buf = to_mx3_vb(vb); + struct mx3_camera_buffer *buf = to_mx3_vb(vbuf); if (!buf->txd) { /* This is for locking debugging only */ @@ -424,7 +428,7 @@ static void mx3_stop_streaming(struct vb2_queue *q) list_for_each_entry_safe(buf, tmp, &mx3_cam->capture, queue) { list_del_init(&buf->queue); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&mx3_cam->lock, flags); diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index 71dd71c0bd1f..efe57b23fac1 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -478,7 +478,7 @@ struct rcar_vin_priv { struct soc_camera_host ici; struct list_head capture; #define MAX_BUFFER_NUM 3 - struct vb2_buffer *queue_buf[MAX_BUFFER_NUM]; + struct vb2_v4l2_buffer *queue_buf[MAX_BUFFER_NUM]; struct vb2_alloc_ctx *alloc_ctx; enum v4l2_field field; unsigned int pdata_flags; @@ -492,7 +492,7 @@ struct rcar_vin_priv { #define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM) struct rcar_vin_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; @@ -527,11 +527,12 @@ struct rcar_vin_cam { * required */ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + 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; @@ -748,7 +749,7 @@ static int rcar_vin_hw_ready(struct rcar_vin_priv *priv) /* Moves a buffer from the queue to the HW slots */ static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv) { - struct vb2_buffer *vb; + struct vb2_v4l2_buffer *vbuf; dma_addr_t phys_addr_top; int slot; @@ -760,10 +761,11 @@ static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv) if (slot < 0) return 0; - vb = &list_entry(priv->capture.next, struct rcar_vin_buffer, list)->vb; - list_del_init(to_buf_list(vb)); - priv->queue_buf[slot] = vb; - phys_addr_top = vb2_dma_contig_plane_dma_addr(vb, 0); + vbuf = &list_entry(priv->capture.next, + struct rcar_vin_buffer, list)->vb; + list_del_init(to_buf_list(vbuf)); + priv->queue_buf[slot] = vbuf; + phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); iowrite32(phys_addr_top, priv->base + VNMB_REG(slot)); return 1; @@ -771,6 +773,7 @@ static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv) static void rcar_vin_videobuf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct rcar_vin_priv *priv = ici->priv; @@ -780,7 +783,7 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb) if (vb2_plane_size(vb, 0) < size) { dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n", - vb->v4l2_buf.index, vb2_plane_size(vb, 0), size); + vb->index, vb2_plane_size(vb, 0), size); goto error; } @@ -791,14 +794,14 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb) spin_lock_irq(&priv->lock); - list_add_tail(to_buf_list(vb), &priv->capture); + list_add_tail(to_buf_list(vbuf), &priv->capture); rcar_vin_fill_hw_slot(priv); /* If we weren't running, and have enough buffers, start capturing! */ if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) { if (rcar_vin_setup(priv)) { /* Submit error */ - list_del_init(to_buf_list(vb)); + list_del_init(to_buf_list(vbuf)); spin_unlock_irq(&priv->lock); goto error; } @@ -854,7 +857,7 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq) for (i = 0; i < MAX_BUFFER_NUM; i++) { if (priv->queue_buf[i]) { - vb2_buffer_done(priv->queue_buf[i], + vb2_buffer_done(&priv->queue_buf[i]->vb2_buf, VB2_BUF_STATE_ERROR); priv->queue_buf[i] = NULL; } @@ -862,7 +865,7 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq) list_for_each_safe(buf_head, tmp, &priv->capture) { vb2_buffer_done(&list_entry(buf_head, - struct rcar_vin_buffer, list)->vb, + struct rcar_vin_buffer, list)->vb.vb2_buf, VB2_BUF_STATE_ERROR); list_del_init(buf_head); } @@ -907,10 +910,11 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) else slot = 0; - priv->queue_buf[slot]->v4l2_buf.field = priv->field; - priv->queue_buf[slot]->v4l2_buf.sequence = priv->sequence++; - v4l2_get_timestamp(&priv->queue_buf[slot]->v4l2_buf.timestamp); - vb2_buffer_done(priv->queue_buf[slot], VB2_BUF_STATE_DONE); + priv->queue_buf[slot]->field = priv->field; + priv->queue_buf[slot]->sequence = priv->sequence++; + v4l2_get_timestamp(&priv->queue_buf[slot]->timestamp); + vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf, + VB2_BUF_STATE_DONE); priv->queue_buf[slot] = NULL; if (priv->state != STOPPING) @@ -964,7 +968,7 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct rcar_vin_priv *priv = ici->priv; - struct vb2_buffer *vb; + struct vb2_v4l2_buffer *vbuf; int i; /* disable capture, disable interrupts */ @@ -978,10 +982,10 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd) /* make sure active buffer is cancelled */ spin_lock_irq(&priv->lock); for (i = 0; i < MAX_BUFFER_NUM; i++) { - vb = priv->queue_buf[i]; - if (vb) { - list_del_init(to_buf_list(vb)); - vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); + vbuf = priv->queue_buf[i]; + if (vbuf) { + list_del_init(to_buf_list(vbuf)); + vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR); } } spin_unlock_irq(&priv->lock); @@ -1602,11 +1606,15 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd, case V4L2_FIELD_INTERLACED: /* Query for standard if not explicitly mentioned _TB/_BT */ ret = v4l2_subdev_call(sd, video, querystd, &std); - if (ret < 0) - std = V4L2_STD_625_50; - - field = std & V4L2_STD_625_50 ? V4L2_FIELD_INTERLACED_TB : - V4L2_FIELD_INTERLACED_BT; + if (ret == -ENOIOCTLCMD) { + field = V4L2_FIELD_NONE; + } else if (ret < 0) { + return ret; + } else { + field = std & V4L2_STD_625_50 ? + V4L2_FIELD_INTERLACED_TB : + V4L2_FIELD_INTERLACED_BT; + } break; } @@ -1846,8 +1854,6 @@ MODULE_DEVICE_TABLE(of, rcar_vin_of_table); #endif static struct platform_device_id rcar_vin_id_table[] = { - { "r8a7791-vin", RCAR_GEN2 }, - { "r8a7790-vin", RCAR_GEN2 }, { "r8a7779-vin", RCAR_H1 }, { "r8a7778-vin", RCAR_M1 }, { "uPD35004-vin", RCAR_E1 }, 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 efdeea4490e8..67a669d826b8 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -93,7 +93,7 @@ /* per video frame buffer */ struct sh_mobile_ceu_buffer { - struct vb2_buffer vb; /* v4l buffer must be first */ + struct vb2_v4l2_buffer vb; /* v4l buffer must be first */ struct list_head queue; }; @@ -112,7 +112,7 @@ struct sh_mobile_ceu_dev { spinlock_t lock; /* Protects video buffer lists */ struct list_head capture; - struct vb2_buffer *active; + struct vb2_v4l2_buffer *active; struct vb2_alloc_ctx *alloc_ctx; struct sh_mobile_ceu_info *pdata; @@ -152,9 +152,9 @@ struct sh_mobile_ceu_cam { u32 code; }; -static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_buffer *vb) +static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_v4l2_buffer *vbuf) { - return container_of(vb, struct sh_mobile_ceu_buffer, vb); + return container_of(vbuf, struct sh_mobile_ceu_buffer, vb); } static void ceu_write(struct sh_mobile_ceu_dev *priv, @@ -210,11 +210,13 @@ 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 struct v4l2_format *fmt, + const void *parg, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq); + 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; @@ -334,7 +336,8 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) bottom2 = CDBCR; } - phys_addr_top = vb2_dma_contig_plane_dma_addr(pcdev->active, 0); + phys_addr_top = + vb2_dma_contig_plane_dma_addr(&pcdev->active->vb2_buf, 0); switch (icd->current_fmt->host_fmt->fourcc) { case V4L2_PIX_FMT_NV12: @@ -369,7 +372,8 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb) { - struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf); /* Added list head initialization on alloc */ WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb); @@ -379,17 +383,19 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb) static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb) { - struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct soc_camera_device *icd = container_of(vb->vb2_queue, + 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; - struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); + struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf); unsigned long size; size = icd->sizeimage; if (vb2_plane_size(vb, 0) < size) { dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n", - vb->v4l2_buf.index, vb2_plane_size(vb, 0), size); + vb->index, vb2_plane_size(vb, 0), size); goto error; } @@ -416,7 +422,7 @@ static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb) * we are not interested in the return value of * sh_mobile_ceu_capture here. */ - pcdev->active = vb; + pcdev->active = vbuf; sh_mobile_ceu_capture(pcdev); } spin_unlock_irq(&pcdev->lock); @@ -429,14 +435,16 @@ error: static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) { - struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct soc_camera_device *icd = container_of(vb->vb2_queue, + struct soc_camera_device, vb2_vidq); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); + struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf); struct sh_mobile_ceu_dev *pcdev = ici->priv; spin_lock_irq(&pcdev->lock); - if (pcdev->active == vb) { + if (pcdev->active == vbuf) { /* disable capture (release DMA buffer), reset */ ceu_write(pcdev, CAPSR, 1 << 16); pcdev->active = NULL; @@ -458,7 +466,9 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) { - struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct soc_camera_device *icd = container_of(vb->vb2_queue, + 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; @@ -467,7 +477,7 @@ static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) pcdev->buf_total); /* This is for locking debugging only */ - INIT_LIST_HEAD(&to_ceu_vb(vb)->queue); + INIT_LIST_HEAD(&to_ceu_vb(vbuf)->queue); return 0; } @@ -504,17 +514,17 @@ static struct vb2_ops sh_mobile_ceu_videobuf_ops = { static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) { struct sh_mobile_ceu_dev *pcdev = data; - struct vb2_buffer *vb; + struct vb2_v4l2_buffer *vbuf; int ret; spin_lock(&pcdev->lock); - vb = pcdev->active; - if (!vb) + vbuf = pcdev->active; + if (!vbuf) /* Stale interrupt from a released buffer */ goto out; - list_del_init(&to_ceu_vb(vb)->queue); + list_del_init(&to_ceu_vb(vbuf)->queue); if (!list_empty(&pcdev->capture)) pcdev->active = &list_entry(pcdev->capture.next, @@ -523,12 +533,13 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) pcdev->active = NULL; ret = sh_mobile_ceu_capture(pcdev); - v4l2_get_timestamp(&vb->v4l2_buf.timestamp); + v4l2_get_timestamp(&vbuf->timestamp); if (!ret) { - vb->v4l2_buf.field = pcdev->field; - vb->v4l2_buf.sequence = pcdev->sequence++; + vbuf->field = pcdev->field; + vbuf->sequence = pcdev->sequence++; } - vb2_buffer_done(vb, ret < 0 ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); + vb2_buffer_done(&vbuf->vb2_buf, + ret < 0 ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); out: spin_unlock(&pcdev->lock); @@ -633,7 +644,7 @@ static void sh_mobile_ceu_clock_stop(struct soc_camera_host *ici) spin_lock_irq(&pcdev->lock); if (pcdev->active) { list_del_init(&to_ceu_vb(pcdev->active)->queue); - vb2_buffer_done(pcdev->active, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&pcdev->active->vb2_buf, VB2_BUF_STATE_ERROR); pcdev->active = NULL; } spin_unlock_irq(&pcdev->lock); diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 9087fed586fb..dc98122e78dc 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -38,7 +38,7 @@ #include <media/v4l2-dev.h> #include <media/v4l2-of.h> #include <media/videobuf-core.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> /* Default to VGA resolution */ #define DEFAULT_WIDTH 640 @@ -1631,7 +1631,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]; + char clk_name[V4L2_SUBDEV_NAME_SIZE + 32]; int ret; /* allocate a new subdev and add match info to it */ diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c index df61355b46f1..a0d267e017f6 100644 --- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c @@ -180,7 +180,7 @@ static struct bdisp_frame *ctx_get_frame(struct bdisp_ctx *ctx, static void bdisp_job_finish(struct bdisp_ctx *ctx, int vb_state) { - struct vb2_buffer *src_vb, *dst_vb; + struct vb2_v4l2_buffer *src_vb, *dst_vb; if (WARN(!ctx || !ctx->fh.m2m_ctx, "Null hardware context\n")) return; @@ -191,10 +191,10 @@ 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->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp; - dst_vb->v4l2_buf.timecode = src_vb->v4l2_buf.timecode; - dst_vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_vb->v4l2_buf.flags |= src_vb->v4l2_buf.flags & + dst_vb->timestamp = src_vb->timestamp; + dst_vb->timecode = src_vb->timecode; + dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_vb->flags |= src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; v4l2_m2m_buf_done(src_vb, vb_state); @@ -281,23 +281,23 @@ static int bdisp_get_addr(struct bdisp_ctx *ctx, struct vb2_buffer *vb, static int bdisp_get_bufs(struct bdisp_ctx *ctx) { struct bdisp_frame *src, *dst; - struct vb2_buffer *src_vb, *dst_vb; + struct vb2_v4l2_buffer *src_vb, *dst_vb; int ret; src = &ctx->src; dst = &ctx->dst; src_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - ret = bdisp_get_addr(ctx, src_vb, src, src->paddr); + ret = bdisp_get_addr(ctx, &src_vb->vb2_buf, src, src->paddr); if (ret) return ret; dst_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); - ret = bdisp_get_addr(ctx, dst_vb, dst, dst->paddr); + ret = bdisp_get_addr(ctx, &dst_vb->vb2_buf, dst, dst->paddr); if (ret) return ret; - dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp; + dst_vb->timestamp = src_vb->timestamp; return 0; } @@ -438,10 +438,11 @@ static void bdisp_ctrls_delete(struct bdisp_ctx *ctx) } static int bdisp_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + 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); @@ -483,6 +484,7 @@ static int bdisp_buf_prepare(struct vb2_buffer *vb) static void bdisp_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct bdisp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); /* return to V4L2 any 0-size buffer so it can be dequeued by user */ @@ -493,13 +495,13 @@ static void bdisp_buf_queue(struct vb2_buffer *vb) } if (ctx->fh.m2m_ctx) - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } static int bdisp_start_streaming(struct vb2_queue *q, unsigned int count) { struct bdisp_ctx *ctx = q->drv_priv; - struct vb2_buffer *buf; + struct vb2_v4l2_buffer *buf; int ret = pm_runtime_get_sync(ctx->bdisp_dev->dev); if (ret < 0) { diff --git a/drivers/media/platform/sti/c8sectpfe/Kconfig b/drivers/media/platform/sti/c8sectpfe/Kconfig index 641ad8f34956..7420a50572d3 100644 --- a/drivers/media/platform/sti/c8sectpfe/Kconfig +++ b/drivers/media/platform/sti/c8sectpfe/Kconfig @@ -3,7 +3,6 @@ config DVB_C8SECTPFE depends on PINCTRL && DVB_CORE && I2C depends on ARCH_STI || ARCH_MULTIPLATFORM || COMPILE_TEST select FW_LOADER - select FW_LOADER_USER_HELPER_FALLBACK select DEBUG_FS select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c index 486aef50d99b..8490a65ae1c6 100644 --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c @@ -1084,10 +1084,10 @@ static void load_dmem_segment(struct c8sectpfei *fei, Elf32_Phdr *phdr, seg_num, phdr->p_paddr, phdr->p_filesz, dst, phdr->p_memsz); - memcpy((void __iomem *)dst, (void *)fw->data + phdr->p_offset, + memcpy((void __force *)dst, (void *)fw->data + phdr->p_offset, phdr->p_filesz); - memset((void __iomem *)dst + phdr->p_filesz, 0, + memset((void __force *)dst + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); } @@ -1097,7 +1097,7 @@ static int load_slim_core_fw(const struct firmware *fw, void *context) Elf32_Ehdr *ehdr; Elf32_Phdr *phdr; u8 __iomem *dst; - int err, i; + int err = 0, i; if (!fw || !context) return -EINVAL; @@ -1106,7 +1106,7 @@ static int load_slim_core_fw(const struct firmware *fw, void *context) phdr = (Elf32_Phdr *)(fw->data + ehdr->e_phoff); /* go through the available ELF segments */ - for (i = 0; i < ehdr->e_phnum && !err; i++, phdr++) { + for (i = 0; i < ehdr->e_phnum; i++, phdr++) { /* Only consider LOAD segments */ if (phdr->p_type != PT_LOAD) @@ -1192,7 +1192,6 @@ err: static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei) { - int ret; int err; dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA); @@ -1207,7 +1206,7 @@ static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei) if (err) { dev_err(fei->dev, "request_firmware_nowait err: %d.\n", err); complete_all(&fei->fw_ack); - return ret; + return err; } return 0; diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index c44760b705da..de24effd984f 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -40,7 +40,7 @@ #include <media/v4l2-event.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-mem2mem.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "vpdma.h" @@ -384,8 +384,8 @@ struct vpe_ctx { unsigned int bufs_completed; /* bufs done in this batch */ struct vpe_q_data q_data[2]; /* src & dst queue data */ - struct vb2_buffer *src_vbs[VPE_MAX_SRC_BUFS]; - struct vb2_buffer *dst_vb; + struct vb2_v4l2_buffer *src_vbs[VPE_MAX_SRC_BUFS]; + struct vb2_v4l2_buffer *dst_vb; dma_addr_t mv_buf_dma[2]; /* dma addrs of motion vector in/out bufs */ void *mv_buf[2]; /* virtual addrs of motion vector bufs */ @@ -988,7 +988,7 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port) { struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_DST]; const struct vpe_port_data *p_data = &port_data[port]; - struct vb2_buffer *vb = ctx->dst_vb; + struct vb2_buffer *vb = &ctx->dst_vb->vb2_buf; struct vpe_fmt *fmt = q_data->fmt; const struct vpdma_data_format *vpdma_fmt; int mv_buf_selector = !ctx->src_mv_buf_selector; @@ -1025,11 +1025,12 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port) { struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC]; const struct vpe_port_data *p_data = &port_data[port]; - struct vb2_buffer *vb = ctx->src_vbs[p_data->vb_index]; + struct vb2_buffer *vb = &ctx->src_vbs[p_data->vb_index]->vb2_buf; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vpe_fmt *fmt = q_data->fmt; const struct vpdma_data_format *vpdma_fmt; int mv_buf_selector = ctx->src_mv_buf_selector; - int field = vb->v4l2_buf.field == V4L2_FIELD_BOTTOM; + int field = vbuf->field == V4L2_FIELD_BOTTOM; int frame_width, frame_height; dma_addr_t dma_addr; u32 flags = 0; @@ -1222,8 +1223,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) struct vpe_dev *dev = (struct vpe_dev *)data; struct vpe_ctx *ctx; struct vpe_q_data *d_q_data; - struct vb2_buffer *s_vb, *d_vb; - struct v4l2_buffer *s_buf, *d_buf; + struct vb2_v4l2_buffer *s_vb, *d_vb; unsigned long flags; u32 irqst0, irqst1; @@ -1286,20 +1286,18 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) s_vb = ctx->src_vbs[0]; d_vb = ctx->dst_vb; - s_buf = &s_vb->v4l2_buf; - d_buf = &d_vb->v4l2_buf; - d_buf->flags = s_buf->flags; + d_vb->flags = s_vb->flags; + d_vb->timestamp = s_vb->timestamp; - d_buf->timestamp = s_buf->timestamp; - if (s_buf->flags & V4L2_BUF_FLAG_TIMECODE) - d_buf->timecode = s_buf->timecode; + if (s_vb->flags & V4L2_BUF_FLAG_TIMECODE) + d_vb->timecode = s_vb->timecode; - d_buf->sequence = ctx->sequence; + d_vb->sequence = ctx->sequence; d_q_data = &ctx->q_data[Q_DATA_DST]; if (d_q_data->flags & Q_DATA_INTERLACED) { - d_buf->field = ctx->field; + d_vb->field = ctx->field; if (ctx->field == V4L2_FIELD_BOTTOM) { ctx->sequence++; ctx->field = V4L2_FIELD_TOP; @@ -1308,7 +1306,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) ctx->field = V4L2_FIELD_BOTTOM; } } else { - d_buf->field = V4L2_FIELD_NONE; + d_vb->field = V4L2_FIELD_NONE; ctx->sequence++; } @@ -1798,7 +1796,7 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { * Queue operations */ static int vpe_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -1825,6 +1823,7 @@ static int vpe_queue_setup(struct vb2_queue *vq, static int vpe_buf_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct vpe_q_data *q_data; int i, num_planes; @@ -1836,10 +1835,10 @@ static int vpe_buf_prepare(struct vb2_buffer *vb) if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if (!(q_data->flags & Q_DATA_INTERLACED)) { - vb->v4l2_buf.field = V4L2_FIELD_NONE; + vbuf->field = V4L2_FIELD_NONE; } else { - if (vb->v4l2_buf.field != V4L2_FIELD_TOP && - vb->v4l2_buf.field != V4L2_FIELD_BOTTOM) + if (vbuf->field != V4L2_FIELD_TOP && + vbuf->field != V4L2_FIELD_BOTTOM) return -EINVAL; } } @@ -1862,9 +1861,10 @@ static int vpe_buf_prepare(struct vb2_buffer *vb) static void vpe_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } static int vpe_start_streaming(struct vb2_queue *q, unsigned int count) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index 295fde5fdb75..e18fb9f9ed2f 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -197,8 +197,8 @@ static struct vim2m_q_data *get_q_data(struct vim2m_ctx *ctx, static int device_process(struct vim2m_ctx *ctx, - struct vb2_buffer *in_vb, - struct vb2_buffer *out_vb) + struct vb2_v4l2_buffer *in_vb, + struct vb2_v4l2_buffer *out_vb) { struct vim2m_dev *dev = ctx->dev; struct vim2m_q_data *q_data; @@ -213,15 +213,16 @@ static int device_process(struct vim2m_ctx *ctx, height = q_data->height; bytesperline = (q_data->width * q_data->fmt->depth) >> 3; - p_in = vb2_plane_vaddr(in_vb, 0); - p_out = vb2_plane_vaddr(out_vb, 0); + p_in = vb2_plane_vaddr(&in_vb->vb2_buf, 0); + p_out = vb2_plane_vaddr(&out_vb->vb2_buf, 0); if (!p_in || !p_out) { v4l2_err(&dev->v4l2_dev, "Acquiring kernel pointers to buffers failed\n"); return -EFAULT; } - if (vb2_plane_size(in_vb, 0) > vb2_plane_size(out_vb, 0)) { + if (vb2_plane_size(&in_vb->vb2_buf, 0) > + vb2_plane_size(&out_vb->vb2_buf, 0)) { v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n"); return -EINVAL; } @@ -231,16 +232,15 @@ static int device_process(struct vim2m_ctx *ctx, bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES; w = 0; - out_vb->v4l2_buf.sequence = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++; - in_vb->v4l2_buf.sequence = q_data->sequence++; - memcpy(&out_vb->v4l2_buf.timestamp, - &in_vb->v4l2_buf.timestamp, - sizeof(struct timeval)); - if (in_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TIMECODE) - memcpy(&out_vb->v4l2_buf.timecode, &in_vb->v4l2_buf.timecode, - sizeof(struct v4l2_timecode)); - out_vb->v4l2_buf.field = in_vb->v4l2_buf.field; - out_vb->v4l2_buf.flags = in_vb->v4l2_buf.flags & + 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; + + if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE) + out_vb->timecode = in_vb->timecode; + out_vb->field = in_vb->field; + out_vb->flags = in_vb->flags & (V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME | @@ -374,7 +374,7 @@ static void device_run(void *priv) { struct vim2m_ctx *ctx = priv; struct vim2m_dev *dev = ctx->dev; - struct vb2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); @@ -389,7 +389,7 @@ static void device_isr(unsigned long priv) { struct vim2m_dev *vim2m_dev = (struct vim2m_dev *)priv; struct vim2m_ctx *curr_ctx; - struct vb2_buffer *src_vb, *dst_vb; + struct vb2_v4l2_buffer *src_vb, *dst_vb; unsigned long flags; curr_ctx = v4l2_m2m_get_curr_priv(vim2m_dev->m2m_dev); @@ -710,10 +710,11 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = { */ static int vim2m_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + 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; @@ -747,6 +748,7 @@ static int vim2m_queue_setup(struct vb2_queue *vq, static int vim2m_buf_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct vim2m_q_data *q_data; @@ -754,9 +756,9 @@ static int vim2m_buf_prepare(struct vb2_buffer *vb) q_data = get_q_data(ctx, vb->vb2_queue->type); if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { - if (vb->v4l2_buf.field == V4L2_FIELD_ANY) - vb->v4l2_buf.field = V4L2_FIELD_NONE; - if (vb->v4l2_buf.field != V4L2_FIELD_NONE) { + if (vbuf->field == V4L2_FIELD_ANY) + vbuf->field = V4L2_FIELD_NONE; + if (vbuf->field != V4L2_FIELD_NONE) { dprintk(ctx->dev, "%s field isn't supported\n", __func__); return -EINVAL; @@ -776,9 +778,10 @@ static int vim2m_buf_prepare(struct vb2_buffer *vb) static void vim2m_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } static int vim2m_start_streaming(struct vb2_queue *q, unsigned count) @@ -793,18 +796,18 @@ static int vim2m_start_streaming(struct vb2_queue *q, unsigned count) static void vim2m_stop_streaming(struct vb2_queue *q) { struct vim2m_ctx *ctx = vb2_get_drv_priv(q); - struct vb2_buffer *vb; + struct vb2_v4l2_buffer *vbuf; unsigned long flags; for (;;) { if (V4L2_TYPE_IS_OUTPUT(q->type)) - vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); else - vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - if (vb == NULL) + vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + if (vbuf == NULL) return; spin_lock_irqsave(&ctx->dev->irqlock, flags); - v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); spin_unlock_irqrestore(&ctx->dev->irqlock, flags); } } diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig index c3090932f06d..0885e93ad436 100644 --- a/drivers/media/platform/vivid/Kconfig +++ b/drivers/media/platform/vivid/Kconfig @@ -20,3 +20,11 @@ config VIDEO_VIVID Say Y here if you want to test video apps or debug V4L devices. When in doubt, say N. + +config VIDEO_VIVID_MAX_DEVS + int "Maximum number of devices" + depends on VIDEO_VIVID + default "64" + ---help--- + This allows you to specify the maximum number of devices supported + by the vivid driver. diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index a047b4716741..ec125becb7af 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -51,7 +51,7 @@ #define VIVID_MODULE_NAME "vivid" /* The maximum number of vivid devices */ -#define VIVID_MAX_DEVS 64 +#define VIVID_MAX_DEVS CONFIG_VIDEO_VIVID_MAX_DEVS MODULE_DESCRIPTION("Virtual Video Test Driver"); MODULE_AUTHOR("Hans Verkuil"); @@ -1341,8 +1341,11 @@ static int vivid_remove(struct platform_device *pdev) struct vivid_dev *dev; unsigned i; - for (i = 0; vivid_devs[i]; i++) { + + for (i = 0; i < n_devs; i++) { dev = vivid_devs[i]; + if (!dev) + continue; if (dev->has_vid_cap) { v4l2_info(&dev->v4l2_dev, "unregistering %s\n", diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h index c72349c83fab..55b304a705d5 100644 --- a/drivers/media/platform/vivid/vivid-core.h +++ b/drivers/media/platform/vivid/vivid-core.h @@ -21,7 +21,7 @@ #define _VIVID_CORE_H_ #include <linux/fb.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/v4l2-device.h> #include <media/v4l2-dev.h> #include <media/v4l2-ctrls.h> @@ -93,7 +93,7 @@ extern struct vivid_fmt vivid_formats[]; /* buffer for one video frame */ struct vivid_buffer { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; @@ -123,6 +123,7 @@ enum vivid_colorspace { VIVID_CS_SRGB, VIVID_CS_ADOBERGB, VIVID_CS_2020, + VIVID_CS_DCI_P3, VIVID_CS_240M, VIVID_CS_SYS_M, VIVID_CS_SYS_BG, @@ -451,6 +452,7 @@ struct vivid_dev { unsigned sdr_buffersize; unsigned sdr_adc_freq; unsigned sdr_fm_freq; + unsigned sdr_fm_deviation; int sdr_fixp_src_phase; int sdr_fixp_mod_phase; diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c index 339c8b7e53c8..f41ac0b01fec 100644 --- a/drivers/media/platform/vivid/vivid-ctrls.c +++ b/drivers/media/platform/vivid/vivid-ctrls.c @@ -99,6 +99,7 @@ #define VIVID_CID_RADIO_TX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 94) +#define VIVID_CID_SDR_CAP_FM_DEVIATION (VIVID_CID_VIVID_BASE + 110) /* General User Controls */ @@ -342,6 +343,7 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl) V4L2_COLORSPACE_SRGB, V4L2_COLORSPACE_ADOBERGB, V4L2_COLORSPACE_BT2020, + V4L2_COLORSPACE_DCI_P3, V4L2_COLORSPACE_SMPTE240M, V4L2_COLORSPACE_470_SYSTEM_M, V4L2_COLORSPACE_470_SYSTEM_BG, @@ -548,7 +550,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_osd_mode = { .id = VIVID_CID_OSD_TEXT_MODE, .name = "OSD Text Mode", .type = V4L2_CTRL_TYPE_MENU, - .max = 2, + .max = ARRAY_SIZE(vivid_ctrl_osd_mode_strings) - 2, .qmenu = vivid_ctrl_osd_mode_strings, }; @@ -640,7 +642,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_tstamp_src = { .id = VIVID_CID_TSTAMP_SRC, .name = "Timestamp Source", .type = V4L2_CTRL_TYPE_MENU, - .max = 1, + .max = ARRAY_SIZE(vivid_ctrl_tstamp_src_strings) - 2, .qmenu = vivid_ctrl_tstamp_src_strings, }; @@ -701,6 +703,7 @@ static const char * const vivid_ctrl_colorspace_strings[] = { "sRGB", "AdobeRGB", "BT.2020", + "DCI-P3", "SMPTE 240M", "470 System M", "470 System BG", @@ -712,7 +715,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_colorspace = { .id = VIVID_CID_COLORSPACE, .name = "Colorspace", .type = V4L2_CTRL_TYPE_MENU, - .max = 7, + .max = ARRAY_SIZE(vivid_ctrl_colorspace_strings) - 2, .def = 2, .qmenu = vivid_ctrl_colorspace_strings, }; @@ -724,6 +727,8 @@ static const char * const vivid_ctrl_xfer_func_strings[] = { "AdobeRGB", "SMPTE 240M", "None", + "DCI-P3", + "SMPTE 2084", NULL, }; @@ -732,7 +737,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_xfer_func = { .id = VIVID_CID_XFER_FUNC, .name = "Transfer Function", .type = V4L2_CTRL_TYPE_MENU, - .max = 5, + .max = ARRAY_SIZE(vivid_ctrl_xfer_func_strings) - 2, .qmenu = vivid_ctrl_xfer_func_strings, }; @@ -754,7 +759,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = { .id = VIVID_CID_YCBCR_ENC, .name = "Y'CbCr Encoding", .type = V4L2_CTRL_TYPE_MENU, - .max = 8, + .max = ARRAY_SIZE(vivid_ctrl_ycbcr_enc_strings) - 2, .qmenu = vivid_ctrl_ycbcr_enc_strings, }; @@ -770,7 +775,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_quantization = { .id = VIVID_CID_QUANTIZATION, .name = "Quantization", .type = V4L2_CTRL_TYPE_MENU, - .max = 2, + .max = ARRAY_SIZE(vivid_ctrl_quantization_strings) - 2, .qmenu = vivid_ctrl_quantization_strings, }; @@ -1088,7 +1093,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_std_signal_mode = { .id = VIVID_CID_STD_SIGNAL_MODE, .name = "Standard Signal Mode", .type = V4L2_CTRL_TYPE_MENU, - .max = 5, + .max = ARRAY_SIZE(vivid_ctrl_std_signal_mode_strings) - 2, .menu_skip_mask = 1 << 3, .qmenu = vivid_ctrl_std_signal_mode_strings, }; @@ -1257,6 +1262,36 @@ static const struct v4l2_ctrl_config vivid_ctrl_radio_tx_rds_blockio = { }; +/* SDR Capture Controls */ + +static int vivid_sdr_cap_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdr_cap); + + switch (ctrl->id) { + case VIVID_CID_SDR_CAP_FM_DEVIATION: + dev->sdr_fm_deviation = ctrl->val; + break; + } + return 0; +} + +static const struct v4l2_ctrl_ops vivid_sdr_cap_ctrl_ops = { + .s_ctrl = vivid_sdr_cap_s_ctrl, +}; + +static const struct v4l2_ctrl_config vivid_ctrl_sdr_cap_fm_deviation = { + .ops = &vivid_sdr_cap_ctrl_ops, + .id = VIVID_CID_SDR_CAP_FM_DEVIATION, + .name = "FM Deviation", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = 100, + .max = 200000, + .def = 75000, + .step = 1, +}; + + static const struct v4l2_ctrl_config vivid_ctrl_class = { .ops = &vivid_user_gen_ctrl_ops, .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY, @@ -1314,7 +1349,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL); v4l2_ctrl_handler_init(hdl_radio_tx, 17); v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL); - v4l2_ctrl_handler_init(hdl_sdr_cap, 18); + v4l2_ctrl_handler_init(hdl_sdr_cap, 19); v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL); /* User Controls */ @@ -1545,6 +1580,10 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, &vivid_radio_tx_ctrl_ops, V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1); } + if (dev->has_sdr_cap) { + v4l2_ctrl_new_custom(hdl_sdr_cap, + &vivid_ctrl_sdr_cap_fm_deviation, NULL); + } if (hdl_user_gen->error) return hdl_user_gen->error; if (hdl_user_vid->error) diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c index 1727f5453f0b..83cc6d3b4784 100644 --- a/drivers/media/platform/vivid/vivid-kthread-cap.c +++ b/drivers/media/platform/vivid/vivid-kthread-cap.c @@ -236,8 +236,8 @@ static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf, void *vbuf; if (p == 0 || tpg_g_buffers(tpg) > 1) - return vb2_plane_vaddr(&buf->vb, p); - vbuf = vb2_plane_vaddr(&buf->vb, 0); + return vb2_plane_vaddr(&buf->vb.vb2_buf, p); + vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); for (i = 0; i < p; i++) vbuf += bpl[i] * h / tpg->vdownsampling[i]; return vbuf; @@ -246,7 +246,7 @@ static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf, static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, struct vivid_buffer *vid_cap_buf) { - bool blank = dev->must_blank[vid_cap_buf->vb.v4l2_buf.index]; + bool blank = dev->must_blank[vid_cap_buf->vb.vb2_buf.index]; struct tpg_data *tpg = &dev->tpg; struct vivid_buffer *vid_out_buf = NULL; unsigned vdiv = dev->fmt_out->vdownsampling[p]; @@ -283,12 +283,12 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, if (vid_out_buf == NULL) return -ENODATA; - vid_cap_buf->vb.v4l2_buf.field = vid_out_buf->vb.v4l2_buf.field; + vid_cap_buf->vb.field = vid_out_buf->vb.field; voutbuf = plane_vaddr(tpg, vid_out_buf, p, dev->bytesperline_out, dev->fmt_out_rect.height); if (p < dev->fmt_out->buffers) - voutbuf += vid_out_buf->vb.v4l2_planes[p].data_offset; + voutbuf += vid_out_buf->vb.vb2_buf.planes[p].data_offset; voutbuf += tpg_hdiv(tpg, p, dev->loop_vid_out.left) + (dev->loop_vid_out.top / vdiv) * stride_out; vcapbuf += tpg_hdiv(tpg, p, dev->compose_cap.left) + @@ -429,17 +429,19 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) bool is_loop = false; if (dev->loop_video && dev->can_loop_video && - ((vivid_is_svid_cap(dev) && !VIVID_INVALID_SIGNAL(dev->std_signal_mode)) || - (vivid_is_hdmi_cap(dev) && !VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode)))) + ((vivid_is_svid_cap(dev) && + !VIVID_INVALID_SIGNAL(dev->std_signal_mode)) || + (vivid_is_hdmi_cap(dev) && + !VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode)))) is_loop = true; - buf->vb.v4l2_buf.sequence = dev->vid_cap_seq_count; + buf->vb.sequence = dev->vid_cap_seq_count; /* * Take the timestamp now if the timestamp source is set to * "Start of Exposure". */ if (dev->tstamp_src_is_soe) - v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + v4l2_get_timestamp(&buf->vb.timestamp); if (dev->field_cap == V4L2_FIELD_ALTERNATE) { /* * 60 Hz standards start with the bottom field, 50 Hz standards @@ -447,19 +449,19 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) * then the field is TOP for 50 Hz and BOTTOM for 60 Hz * standards. */ - buf->vb.v4l2_buf.field = ((dev->vid_cap_seq_count & 1) ^ is_60hz) ? + buf->vb.field = ((dev->vid_cap_seq_count & 1) ^ is_60hz) ? V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP; /* * The sequence counter counts frames, not fields. So divide * by two. */ - buf->vb.v4l2_buf.sequence /= 2; + buf->vb.sequence /= 2; } else { - buf->vb.v4l2_buf.field = dev->field_cap; + buf->vb.field = dev->field_cap; } - tpg_s_field(tpg, buf->vb.v4l2_buf.field, + tpg_s_field(tpg, buf->vb.field, dev->field_cap == V4L2_FIELD_ALTERNATE); - tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.v4l2_buf.index]); + tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.vb2_buf.index]); vivid_precalc_copy_rects(dev); @@ -479,13 +481,16 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) } tpg_calc_text_basep(tpg, basep, p, vbuf); if (!is_loop || vivid_copy_buffer(dev, p, vbuf, buf)) - tpg_fill_plane_buffer(tpg, vivid_get_std_cap(dev), p, vbuf); + tpg_fill_plane_buffer(tpg, vivid_get_std_cap(dev), + p, vbuf); } - dev->must_blank[buf->vb.v4l2_buf.index] = false; + dev->must_blank[buf->vb.vb2_buf.index] = false; /* Updates stream time, only update at the start of a new frame. */ - if (dev->field_cap != V4L2_FIELD_ALTERNATE || (buf->vb.v4l2_buf.sequence & 1) == 0) - dev->ms_vid_cap = jiffies_to_msecs(jiffies - dev->jiffies_vid_cap); + if (dev->field_cap != V4L2_FIELD_ALTERNATE || + (buf->vb.sequence & 1) == 0) + dev->ms_vid_cap = + jiffies_to_msecs(jiffies - dev->jiffies_vid_cap); ms = dev->ms_vid_cap; if (dev->osd_mode <= 1) { @@ -494,9 +499,9 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) (ms / (60 * 1000)) % 60, (ms / 1000) % 60, ms % 1000, - buf->vb.v4l2_buf.sequence, + buf->vb.sequence, (dev->field_cap == V4L2_FIELD_ALTERNATE) ? - (buf->vb.v4l2_buf.field == V4L2_FIELD_TOP ? + (buf->vb.field == V4L2_FIELD_TOP ? " top" : " bottom") : ""); tpg_gen_text(tpg, basep, line++ * line_height, 16, str); } @@ -553,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.v4l2_buf.timestamp); - buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset; + v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.timestamp.tv_sec += dev->time_wrap_offset; } /* @@ -600,7 +605,7 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf) struct tpg_data *tpg = &dev->tpg; unsigned pixsize = tpg_g_twopixelsize(tpg, 0) / 2; void *vbase = dev->fb_vbase_cap; - void *vbuf = vb2_plane_vaddr(&buf->vb, 0); + void *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); unsigned img_width = dev->compose_cap.width; unsigned img_height = dev->compose_cap.height; unsigned stride = tpg->bytesperline[0]; @@ -616,7 +621,7 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf) return; if ((dev->overlay_cap_field == V4L2_FIELD_TOP || dev->overlay_cap_field == V4L2_FIELD_BOTTOM) && - dev->overlay_cap_field != buf->vb.v4l2_buf.field) + dev->overlay_cap_field != buf->vb.field) return; vbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride; @@ -699,17 +704,17 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs) /* Fill buffer */ vivid_fillbuff(dev, vid_cap_buf); dprintk(dev, 1, "filled buffer %d\n", - vid_cap_buf->vb.v4l2_buf.index); + vid_cap_buf->vb.vb2_buf.index); /* Handle overlay */ if (dev->overlay_cap_owner && dev->fb_cap.base && - dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc) + dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc) vivid_overlay(dev, vid_cap_buf); - vb2_buffer_done(&vid_cap_buf->vb, dev->dqbuf_error ? + vb2_buffer_done(&vid_cap_buf->vb.vb2_buf, dev->dqbuf_error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); dprintk(dev, 2, "vid_cap buffer %d done\n", - vid_cap_buf->vb.v4l2_buf.index); + vid_cap_buf->vb.vb2_buf.index); } if (vbi_cap_buf) { @@ -717,10 +722,10 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs) vivid_sliced_vbi_cap_process(dev, vbi_cap_buf); else vivid_raw_vbi_cap_process(dev, vbi_cap_buf); - vb2_buffer_done(&vbi_cap_buf->vb, dev->dqbuf_error ? + vb2_buffer_done(&vbi_cap_buf->vb.vb2_buf, dev->dqbuf_error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); dprintk(dev, 2, "vbi_cap %d done\n", - vbi_cap_buf->vb.v4l2_buf.index); + vbi_cap_buf->vb.vb2_buf.index); } dev->dqbuf_error = false; @@ -884,9 +889,9 @@ void vivid_stop_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming) buf = list_entry(dev->vid_cap_active.next, struct vivid_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); dprintk(dev, 2, "vid_cap buffer %d done\n", - buf->vb.v4l2_buf.index); + buf->vb.vb2_buf.index); } } @@ -897,9 +902,9 @@ void vivid_stop_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming) buf = list_entry(dev->vbi_cap_active.next, struct vivid_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); dprintk(dev, 2, "vbi_cap buffer %d done\n", - buf->vb.v4l2_buf.index); + buf->vb.vb2_buf.index); } } diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c index d9f36ccd7efb..c2c46dcdbe95 100644 --- a/drivers/media/platform/vivid/vivid-kthread-out.c +++ b/drivers/media/platform/vivid/vivid-kthread-out.c @@ -87,33 +87,33 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev) return; if (vid_out_buf) { - vid_out_buf->vb.v4l2_buf.sequence = dev->vid_out_seq_count; + vid_out_buf->vb.sequence = dev->vid_out_seq_count; if (dev->field_out == V4L2_FIELD_ALTERNATE) { /* - * The sequence counter counts frames, not fields. So divide - * by two. + * The sequence counter counts frames, not fields. + * So divide by two. */ - vid_out_buf->vb.v4l2_buf.sequence /= 2; + vid_out_buf->vb.sequence /= 2; } - v4l2_get_timestamp(&vid_out_buf->vb.v4l2_buf.timestamp); - vid_out_buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset; - vb2_buffer_done(&vid_out_buf->vb, dev->dqbuf_error ? + v4l2_get_timestamp(&vid_out_buf->vb.timestamp); + vid_out_buf->vb.timestamp.tv_sec += 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", - vid_out_buf->vb.v4l2_buf.index); + vid_out_buf->vb.vb2_buf.index); } if (vbi_out_buf) { if (dev->stream_sliced_vbi_out) vivid_sliced_vbi_out_process(dev, vbi_out_buf); - vbi_out_buf->vb.v4l2_buf.sequence = dev->vbi_out_seq_count; - v4l2_get_timestamp(&vbi_out_buf->vb.v4l2_buf.timestamp); - vbi_out_buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset; - vb2_buffer_done(&vbi_out_buf->vb, dev->dqbuf_error ? + 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; + 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", - vbi_out_buf->vb.v4l2_buf.index); + vbi_out_buf->vb.vb2_buf.index); } dev->dqbuf_error = false; } @@ -274,9 +274,9 @@ void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming) buf = list_entry(dev->vid_out_active.next, struct vivid_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); dprintk(dev, 2, "vid_out buffer %d done\n", - buf->vb.v4l2_buf.index); + buf->vb.vb2_buf.index); } } @@ -287,9 +287,9 @@ void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming) buf = list_entry(dev->vbi_out_active.next, struct vivid_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); dprintk(dev, 2, "vbi_out buffer %d done\n", - buf->vb.v4l2_buf.index); + buf->vb.vb2_buf.index); } } diff --git a/drivers/media/platform/vivid/vivid-osd.c b/drivers/media/platform/vivid/vivid-osd.c index 084d346fb4c4..e15eef6a94e5 100644 --- a/drivers/media/platform/vivid/vivid-osd.c +++ b/drivers/media/platform/vivid/vivid-osd.c @@ -85,6 +85,7 @@ static int vivid_fb_ioctl(struct fb_info *info, unsigned cmd, unsigned long arg) case FBIOGET_VBLANK: { struct fb_vblank vblank; + memset(&vblank, 0, sizeof(vblank)); vblank.flags = FB_VBLANK_HAVE_COUNT | FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC; vblank.count = 0; diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c index d2f2188a0efe..082c401764ce 100644 --- a/drivers/media/platform/vivid/vivid-sdr-cap.c +++ b/drivers/media/platform/vivid/vivid-sdr-cap.c @@ -22,6 +22,7 @@ #include <linux/delay.h> #include <linux/kthread.h> #include <linux/freezer.h> +#include <linux/math64.h> #include <linux/videodev2.h> #include <linux/v4l2-dv-timings.h> #include <media/v4l2-common.h> @@ -40,7 +41,7 @@ struct vivid_format { }; /* format descriptions for capture and preview */ -static struct vivid_format formats[] = { +static const struct vivid_format formats[] = { { .pixelformat = V4L2_SDR_FMT_CU8, .buffersize = SDR_CAP_SAMPLES_PER_BUF * 2, @@ -114,11 +115,11 @@ static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev) spin_unlock(&dev->slock); if (sdr_cap_buf) { - sdr_cap_buf->vb.v4l2_buf.sequence = dev->sdr_cap_seq_count; + 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.v4l2_buf.timestamp); - sdr_cap_buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset; - vb2_buffer_done(&sdr_cap_buf->vb, dev->dqbuf_error ? + v4l2_get_timestamp(&sdr_cap_buf->vb.timestamp); + sdr_cap_buf->vb.timestamp.tv_sec += 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; } @@ -161,7 +162,8 @@ static int vivid_thread_sdr_cap(void *data) /* Calculate the number of jiffies since we started streaming */ jiffies_since_start = cur_jiffies - dev->jiffies_sdr_cap; /* Get the number of buffers streamed since the start */ - buffers_since_start = (u64)jiffies_since_start * dev->sdr_adc_freq + + buffers_since_start = + (u64)jiffies_since_start * dev->sdr_adc_freq + (HZ * SDR_CAP_SAMPLES_PER_BUF) / 2; do_div(buffers_since_start, HZ * SDR_CAP_SAMPLES_PER_BUF); @@ -176,7 +178,8 @@ static int vivid_thread_sdr_cap(void *data) dev->sdr_cap_seq_offset = buffers_since_start; buffers_since_start = 0; } - dev->sdr_cap_seq_count = buffers_since_start + dev->sdr_cap_seq_offset; + dev->sdr_cap_seq_count = + buffers_since_start + dev->sdr_cap_seq_offset; vivid_thread_sdr_cap_tick(dev); mutex_unlock(&dev->mutex); @@ -210,7 +213,7 @@ static int vivid_thread_sdr_cap(void *data) return 0; } -static int sdr_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int sdr_cap_queue_setup(struct vb2_queue *vq, const void *parg, unsigned *nbuffers, unsigned *nplanes, unsigned sizes[], void *alloc_ctxs[]) { @@ -247,8 +250,9 @@ static int sdr_cap_buf_prepare(struct vb2_buffer *vb) static void sdr_cap_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct vivid_buffer *buf = container_of(vb, struct vivid_buffer, vb); + struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb); dprintk(dev, 1, "%s\n", __func__); @@ -282,7 +286,8 @@ static int sdr_cap_start_streaming(struct vb2_queue *vq, unsigned count) list_for_each_entry_safe(buf, tmp, &dev->sdr_cap_active, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_QUEUED); } } return err; @@ -299,9 +304,10 @@ static void sdr_cap_stop_streaming(struct vb2_queue *vq) while (!list_empty(&dev->sdr_cap_active)) { struct vivid_buffer *buf; - buf = list_entry(dev->sdr_cap_active.next, struct vivid_buffer, list); + buf = list_entry(dev->sdr_cap_active.next, + struct vivid_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } /* shutdown control thread */ @@ -321,7 +327,8 @@ const struct vb2_ops vivid_sdr_cap_qops = { .wait_finish = vb2_ops_wait_finish, }; -int vivid_sdr_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band) +int vivid_sdr_enum_freq_bands(struct file *file, void *fh, + struct v4l2_frequency_band *band) { switch (band->tuner) { case 0: @@ -339,7 +346,8 @@ int vivid_sdr_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency } } -int vivid_sdr_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) +int vivid_sdr_g_frequency(struct file *file, void *fh, + struct v4l2_frequency *vf) { struct vivid_dev *dev = video_drvdata(file); @@ -357,7 +365,8 @@ int vivid_sdr_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf } } -int vivid_sdr_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf) +int vivid_sdr_s_frequency(struct file *file, void *fh, + const struct v4l2_frequency *vf) { struct vivid_dev *dev = video_drvdata(file); unsigned freq = vf->frequency; @@ -403,14 +412,16 @@ int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) case 0: strlcpy(vt->name, "ADC", sizeof(vt->name)); vt->type = V4L2_TUNER_ADC; - vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; + vt->capability = + V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; vt->rangelow = bands_adc[0].rangelow; vt->rangehigh = bands_adc[2].rangehigh; return 0; case 1: strlcpy(vt->name, "RF", sizeof(vt->name)); vt->type = V4L2_TUNER_RF; - vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; + vt->capability = + V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; vt->rangelow = bands_fm[0].rangelow; vt->rangehigh = bands_fm[0].rangehigh; return 0; @@ -488,47 +499,42 @@ int vidioc_try_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f) #define FIXP_N (15) #define FIXP_FRAC (1 << FIXP_N) #define FIXP_2PI ((int)(2 * 3.141592653589 * FIXP_FRAC)) +#define M_100000PI (3.14159 * 100000) void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf) { - u8 *vbuf = vb2_plane_vaddr(&buf->vb, 0); + u8 *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); unsigned long i; - unsigned long plane_size = vb2_plane_size(&buf->vb, 0); + unsigned long plane_size = vb2_plane_size(&buf->vb.vb2_buf, 0); + s64 s64tmp; s32 src_phase_step; s32 mod_phase_step; s32 fixp_i; s32 fixp_q; - /* - * TODO: Generated beep tone goes very crackly when sample rate is - * increased to ~1Msps or more. That is because of huge rounding error - * of phase angle caused by used cosine implementation. - */ - /* calculate phase step */ #define BEEP_FREQ 1000 /* 1kHz beep */ src_phase_step = DIV_ROUND_CLOSEST(FIXP_2PI * BEEP_FREQ, - dev->sdr_adc_freq); + dev->sdr_adc_freq); for (i = 0; i < plane_size; i += 2) { mod_phase_step = fixp_cos32_rad(dev->sdr_fixp_src_phase, FIXP_2PI) >> (31 - FIXP_N); dev->sdr_fixp_src_phase += src_phase_step; - dev->sdr_fixp_mod_phase += mod_phase_step / 4; + s64tmp = (s64) mod_phase_step * dev->sdr_fm_deviation; + dev->sdr_fixp_mod_phase += div_s64(s64tmp, M_100000PI); /* - * Transfer phases to [0 / 2xPI] in order to avoid variable + * Transfer phase angle to [0, 2xPI] in order to avoid variable * overflow and make it suitable for cosine implementation * used, which does not support negative angles. */ - while (dev->sdr_fixp_mod_phase < FIXP_2PI) - dev->sdr_fixp_mod_phase += FIXP_2PI; - while (dev->sdr_fixp_mod_phase > FIXP_2PI) - dev->sdr_fixp_mod_phase -= FIXP_2PI; + dev->sdr_fixp_src_phase %= FIXP_2PI; + dev->sdr_fixp_mod_phase %= FIXP_2PI; - while (dev->sdr_fixp_src_phase > FIXP_2PI) - dev->sdr_fixp_src_phase -= FIXP_2PI; + if (dev->sdr_fixp_mod_phase < 0) + dev->sdr_fixp_mod_phase += FIXP_2PI; fixp_i = fixp_cos32_rad(dev->sdr_fixp_mod_phase, FIXP_2PI); fixp_q = fixp_sin32_rad(dev->sdr_fixp_mod_phase, FIXP_2PI); @@ -540,7 +546,7 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf) switch (dev->sdr_pixelformat) { case V4L2_SDR_FMT_CU8: - /* convert 'fixp float' to u8 */ + /* convert 'fixp float' to u8 [0, +255] */ /* u8 = X * 127.5 + 127.5; X is float [-1.0, +1.0] */ fixp_i = fixp_i * 1275 + FIXP_FRAC * 1275; fixp_q = fixp_q * 1275 + FIXP_FRAC * 1275; @@ -548,9 +554,10 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf) *vbuf++ = DIV_ROUND_CLOSEST(fixp_q, FIXP_FRAC * 10); break; case V4L2_SDR_FMT_CS8: - /* convert 'fixp float' to s8 */ - fixp_i = fixp_i * 1275; - fixp_q = fixp_q * 1275; + /* convert 'fixp float' to s8 [-128, +127] */ + /* s8 = X * 127.5 - 0.5; X is float [-1.0, +1.0] */ + fixp_i = fixp_i * 1275 - FIXP_FRAC * 5; + fixp_q = fixp_q * 1275 - FIXP_FRAC * 5; *vbuf++ = DIV_ROUND_CLOSEST(fixp_i, FIXP_FRAC * 10); *vbuf++ = DIV_ROUND_CLOSEST(fixp_q, FIXP_FRAC * 10); break; diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.c b/drivers/media/platform/vivid/vivid-tpg-colors.c index 8f231a6e68c9..2299f0ce47c8 100644 --- a/drivers/media/platform/vivid/vivid-tpg-colors.c +++ b/drivers/media/platform/vivid/vivid-tpg-colors.c @@ -598,7 +598,7 @@ const unsigned short tpg_linear_to_rec709[255 * 16 + 1] = { }; /* Generated table */ -const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_NONE + 1][TPG_COLOR_CSC_BLACK + 1] = { +const struct color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFER_FUNC_SMPTE2084 + 1][TPG_COLOR_CSC_BLACK + 1] = { [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_709][1] = { 2953, 2963, 586 }, [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_709][2] = { 0, 2967, 2937 }, @@ -639,6 +639,22 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_NONE][5] = { 2256, 90, 133 }, [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_NONE][6] = { 110, 96, 2113 }, [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][1] = { 3186, 3194, 1121 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][2] = { 0, 3197, 3173 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][3] = { 523, 3216, 1112 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][4] = { 3237, 792, 3169 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][5] = { 3248, 944, 1094 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][6] = { 1017, 967, 3168 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][1] = { 3802, 3805, 2602 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][2] = { 0, 3806, 3797 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][3] = { 1780, 3812, 2592 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][4] = { 3820, 2215, 3796 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][5] = { 3824, 2409, 2574 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][6] = { 2491, 2435, 3795 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 }, [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_709][1] = { 2953, 2963, 586 }, [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_709][2] = { 0, 2967, 2937 }, @@ -679,6 +695,22 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_NONE][5] = { 2256, 90, 133 }, [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_NONE][6] = { 110, 96, 2113 }, [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][1] = { 3186, 3194, 1121 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][2] = { 0, 3197, 3173 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][3] = { 523, 3216, 1112 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][4] = { 3237, 792, 3169 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][5] = { 3248, 944, 1094 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][6] = { 1017, 967, 3168 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][1] = { 3802, 3805, 2602 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][2] = { 0, 3806, 3797 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][3] = { 1780, 3812, 2592 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][4] = { 3820, 2215, 3796 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][5] = { 3824, 2409, 2574 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][6] = { 2491, 2435, 3795 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 }, [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 547 }, [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_709][2] = { 547, 2939, 2939 }, @@ -719,46 +751,78 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_NONE][5] = { 2125, 130, 130 }, [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2125 }, [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][0] = { 2892, 2988, 2807 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][1] = { 2846, 3070, 843 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][2] = { 1656, 2962, 2783 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][3] = { 1572, 3045, 763 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][4] = { 2476, 229, 2742 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][5] = { 2420, 672, 614 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][6] = { 725, 63, 2718 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][7] = { 534, 561, 509 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][0] = { 3013, 3099, 2935 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][1] = { 2970, 3174, 1091 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][2] = { 1871, 3076, 2913 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][3] = { 1791, 3152, 1013 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][4] = { 2632, 468, 2876 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][5] = { 2581, 924, 866 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][6] = { 976, 180, 2854 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][7] = { 786, 813, 762 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][0] = { 2990, 3077, 2912 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][1] = { 2947, 3153, 1119 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][2] = { 1859, 3053, 2889 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][3] = { 1782, 3130, 1047 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][4] = { 2608, 556, 2852 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][5] = { 2557, 964, 912 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][6] = { 1013, 309, 2830 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][7] = { 839, 864, 817 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2879, 2975, 2793 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2832, 3059, 806 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][2] = { 1629, 2949, 2768 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][3] = { 1543, 3033, 725 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][4] = { 2457, 203, 2727 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][5] = { 2401, 633, 574 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][6] = { 687, 56, 2702 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][7] = { 493, 521, 469 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][0] = { 2060, 2194, 1943 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][1] = { 1995, 2314, 237 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][2] = { 725, 2157, 1911 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][3] = { 660, 2278, 205 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][4] = { 1525, 50, 1857 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][5] = { 1461, 171, 151 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][6] = { 190, 14, 1825 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][7] = { 126, 134, 118 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1084 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][2] = { 1084, 3175, 3175 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][3] = { 1084, 3175, 1084 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][4] = { 3175, 1084, 3175 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][5] = { 3175, 1084, 1084 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3175 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][1] = { 3798, 3798, 2563 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][2] = { 2563, 3798, 3798 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][3] = { 2563, 3798, 2563 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][4] = { 3798, 2563, 3798 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][5] = { 3798, 2563, 2563 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][6] = { 2563, 2563, 3798 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][1] = { 2892, 3034, 910 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][2] = { 1715, 2916, 2914 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][3] = { 1631, 3012, 828 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][4] = { 2497, 119, 2867 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][5] = { 2440, 649, 657 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][6] = { 740, 0, 2841 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_709][7] = { 547, 547, 547 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][0] = { 3056, 3055, 3056 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][1] = { 3013, 3142, 1157 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][2] = { 1926, 3034, 3032 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][3] = { 1847, 3121, 1076 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][4] = { 2651, 304, 2990 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][5] = { 2599, 901, 909 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][6] = { 991, 0, 2966 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][1] = { 2989, 3120, 1180 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][2] = { 1913, 3011, 3009 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][3] = { 1836, 3099, 1105 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][4] = { 2627, 413, 2966 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][5] = { 2576, 943, 951 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][6] = { 1026, 0, 2942 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2879, 3022, 874 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][2] = { 1688, 2903, 2901 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][3] = { 1603, 2999, 791 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][4] = { 2479, 106, 2853 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][5] = { 2422, 610, 618 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][6] = { 702, 0, 2827 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][7] = { 507, 507, 507 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][0] = { 2125, 2125, 2125 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][1] = { 2059, 2262, 266 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][2] = { 771, 2092, 2089 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][3] = { 705, 2229, 231 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][4] = { 1550, 26, 2024 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][5] = { 1484, 163, 165 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][6] = { 196, 0, 1988 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][1] = { 3136, 3251, 1429 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][2] = { 2150, 3156, 3154 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][3] = { 2077, 3233, 1352 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][4] = { 2812, 589, 3116 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][5] = { 2765, 1182, 1190 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][6] = { 1270, 0, 3094 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][1] = { 3784, 3825, 2879 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][2] = { 3351, 3791, 3790 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][3] = { 3311, 3819, 2815 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][4] = { 3659, 1900, 3777 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][5] = { 3640, 2662, 2669 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][6] = { 2743, 0, 3769 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 }, [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 464 }, [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_709][2] = { 786, 2939, 2939 }, @@ -799,6 +863,22 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_NONE][5] = { 2041, 130, 130 }, [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2149 }, [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1003 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][2] = { 1313, 3175, 3175 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][3] = { 1313, 3175, 1003 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][4] = { 3126, 1084, 3188 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][5] = { 3126, 1084, 1084 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3188 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][1] = { 3798, 3798, 2476 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][2] = { 2782, 3798, 3798 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][3] = { 2782, 3798, 2476 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][4] = { 3780, 2563, 3803 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][5] = { 3780, 2563, 2563 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][6] = { 2563, 2563, 3803 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 547 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_709][2] = { 547, 2939, 2939 }, @@ -839,6 +919,22 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_NONE][5] = { 2125, 130, 130 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2125 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1084 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][2] = { 1084, 3175, 3175 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][3] = { 1084, 3175, 1084 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][4] = { 3175, 1084, 3175 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][5] = { 3175, 1084, 1084 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3175 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][1] = { 3798, 3798, 2563 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][2] = { 2563, 3798, 3798 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][3] = { 2563, 3798, 2563 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][4] = { 3798, 2563, 3798 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 3798, 2563, 2563 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 2563, 2563, 3798 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 }, [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 781 }, [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][2] = { 1622, 2939, 2939 }, @@ -879,6 +975,22 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][5] = { 1557, 130, 130 }, [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2043 }, [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1308 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][2] = { 2069, 3175, 3175 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][3] = { 2069, 3175, 1308 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][4] = { 2816, 1084, 3127 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][5] = { 2816, 1084, 1084 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3127 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][1] = { 3798, 3798, 2778 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][2] = { 3306, 3798, 3798 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][3] = { 3306, 3798, 2778 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][4] = { 3661, 2563, 3781 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 3661, 2563, 2563 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 2563, 2563, 3781 }, + [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][1] = { 2877, 2923, 1058 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][2] = { 1837, 2840, 2916 }, @@ -919,6 +1031,78 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_NONE][5] = { 1382, 268, 162 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_NONE][6] = { 216, 152, 1917 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][1] = { 3124, 3161, 1566 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][2] = { 2255, 3094, 3156 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][3] = { 2166, 3080, 1506 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][4] = { 2754, 1477, 3071 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][5] = { 2690, 1431, 1182 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][6] = { 1318, 1153, 3051 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][1] = { 3780, 3793, 2984 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][2] = { 3406, 3768, 3791 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][3] = { 3359, 3763, 2939 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][4] = { 3636, 2916, 3760 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][5] = { 3609, 2880, 2661 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][6] = { 2786, 2633, 3753 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][1] = { 2936, 2934, 992 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][2] = { 1159, 2890, 2916 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][3] = { 1150, 2885, 921 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][4] = { 2751, 766, 2837 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][5] = { 2747, 747, 650 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][6] = { 563, 570, 2812 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_709][7] = { 547, 547, 547 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][0] = { 3056, 3056, 3055 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][1] = { 3052, 3051, 1237 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][2] = { 1397, 3011, 3034 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][3] = { 1389, 3006, 1168 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][4] = { 2884, 1016, 2962 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][5] = { 2880, 998, 902 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][6] = { 816, 823, 2940 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 799 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][1] = { 3029, 3028, 1255 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][2] = { 1406, 2988, 3011 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][3] = { 1398, 2983, 1190 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][4] = { 2860, 1050, 2939 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][5] = { 2857, 1033, 945 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][6] = { 866, 873, 2916 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][1] = { 2923, 2921, 957 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][2] = { 1125, 2877, 2902 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][3] = { 1116, 2871, 885 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][4] = { 2736, 729, 2823 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][5] = { 2732, 710, 611 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][6] = { 523, 531, 2798 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][7] = { 507, 507, 507 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][0] = { 2125, 2125, 2125 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][1] = { 2120, 2118, 305 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][2] = { 392, 2056, 2092 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][3] = { 387, 2049, 271 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][4] = { 1868, 206, 1983 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][5] = { 1863, 199, 163 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][6] = { 135, 137, 1950 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][1] = { 3172, 3170, 1505 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][2] = { 1657, 3135, 3155 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][3] = { 1649, 3130, 1439 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][4] = { 3021, 1294, 3091 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][5] = { 3018, 1276, 1184 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][6] = { 1100, 1107, 3071 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][0] = { 3798, 3798, 3798 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][1] = { 3797, 3796, 2938 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][2] = { 3049, 3783, 3791 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][3] = { 3044, 3782, 2887 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][4] = { 3741, 2765, 3768 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][5] = { 3740, 2749, 2663 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][6] = { 2580, 2587, 3760 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE2084][7] = { 2563, 2563, 2563 }, }; #else @@ -930,9 +1114,13 @@ const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_N #include <stdlib.h> static const double rec709_to_ntsc1953[3][3] = { - { 0.6689794, 0.2678309, 0.0323187 }, - { 0.0184901, 1.0742442, -0.0602820 }, - { 0.0162259, 0.0431716, 0.8549253 } + /* + * This transform uses the Bradford method to compensate for + * the different whitepoints. + */ + { 0.6785011, 0.2883441, 0.0331548 }, + { 0.0165284, 1.0518725, -0.0684009 }, + { 0.0179230, 0.0506096, 0.9314674 } }; static const double rec709_to_ebu[3][3] = { @@ -965,6 +1153,16 @@ static const double rec709_to_bt2020[3][3] = { { 0.0163976, 0.0880301, 0.8955723 }, }; +static const double rec709_to_dcip3[3][3] = { + /* + * This transform uses the Bradford method to compensate for + * the different whitepoints. + */ + { 0.8686648, 0.1288456, 0.0024896 }, + { 0.0345479, 0.9618084, 0.0036437 }, + { 0.0167785, 0.0710559, 0.9121655 } +}; + static void mult_matrix(double *r, double *g, double *b, const double m[3][3]) { double ir, ig, ib; @@ -1015,6 +1213,23 @@ static double transfer_rgb_to_adobergb(double v) return pow(v, 1.0 / 2.19921875); } +static double transfer_rgb_to_dcip3(double v) +{ + return pow(v, 1.0 / 2.6); +} + +static double transfer_rgb_to_smpte2084(double v) +{ + const double m1 = (2610.0 / 4096.0) / 4.0; + const double m2 = 128.0 * 2523.0 / 4096.0; + const double c1 = 3424.0 / 4096.0; + const double c2 = 32.0 * 2413.0 / 4096.0; + const double c3 = 32.0 * 2392.0 / 4096.0; + + v = pow(v, m1); + return pow((c1 + c2 * v) / (1 + c3 * v), m2); +} + static double transfer_srgb_to_rec709(double v) { return transfer_rgb_to_rec709(transfer_srgb_to_rgb(v)); @@ -1049,6 +1264,9 @@ static void csc(enum v4l2_colorspace colorspace, enum v4l2_xfer_func xfer_func, case V4L2_COLORSPACE_BT2020: mult_matrix(r, g, b, rec709_to_bt2020); break; + case V4L2_COLORSPACE_DCI_P3: + mult_matrix(r, g, b, rec709_to_dcip3); + break; case V4L2_COLORSPACE_SRGB: case V4L2_COLORSPACE_REC709: break; @@ -1078,6 +1296,16 @@ static void csc(enum v4l2_colorspace colorspace, enum v4l2_xfer_func xfer_func, *g = transfer_rgb_to_adobergb(*g); *b = transfer_rgb_to_adobergb(*b); break; + case V4L2_XFER_FUNC_DCI_P3: + *r = transfer_rgb_to_dcip3(*r); + *g = transfer_rgb_to_dcip3(*g); + *b = transfer_rgb_to_dcip3(*b); + break; + case V4L2_XFER_FUNC_SMPTE2084: + *r = transfer_rgb_to_smpte2084(*r); + *g = transfer_rgb_to_smpte2084(*g); + *b = transfer_rgb_to_smpte2084(*b); + break; case V4L2_XFER_FUNC_SMPTE240M: *r = transfer_rgb_to_smpte240m(*r); *g = transfer_rgb_to_smpte240m(*g); @@ -1102,6 +1330,8 @@ int main(int argc, char **argv) V4L2_COLORSPACE_SRGB, V4L2_COLORSPACE_ADOBERGB, V4L2_COLORSPACE_BT2020, + 0, + V4L2_COLORSPACE_DCI_P3, }; static const char * const colorspace_names[] = { "", @@ -1115,6 +1345,8 @@ int main(int argc, char **argv) "V4L2_COLORSPACE_SRGB", "V4L2_COLORSPACE_ADOBERGB", "V4L2_COLORSPACE_BT2020", + "", + "V4L2_COLORSPACE_DCI_P3", }; static const char * const xfer_func_names[] = { "", @@ -1123,6 +1355,8 @@ int main(int argc, char **argv) "V4L2_XFER_FUNC_ADOBERGB", "V4L2_XFER_FUNC_SMPTE240M", "V4L2_XFER_FUNC_NONE", + "V4L2_XFER_FUNC_DCI_P3", + "V4L2_XFER_FUNC_SMPTE2084", }; int i; int x; @@ -1153,9 +1387,9 @@ int main(int argc, char **argv) printf("\n};\n\n"); printf("/* Generated table */\n"); - printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][V4L2_XFER_FUNC_NONE + 1][TPG_COLOR_CSC_BLACK + 1] = {\n"); - for (c = 0; c <= V4L2_COLORSPACE_BT2020; c++) { - for (x = 1; x <= V4L2_XFER_FUNC_NONE; x++) { + printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFER_FUNC_SMPTE2084 + 1][TPG_COLOR_CSC_BLACK + 1] = {\n"); + for (c = 0; c <= V4L2_COLORSPACE_DCI_P3; c++) { + for (x = 1; x <= V4L2_XFER_FUNC_SMPTE2084; x++) { for (i = 0; i <= TPG_COLOR_CSC_BLACK; i++) { double r, g, b; diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.h b/drivers/media/platform/vivid/vivid-tpg-colors.h index 86b8bf3fe745..4e5a76a1e25b 100644 --- a/drivers/media/platform/vivid/vivid-tpg-colors.h +++ b/drivers/media/platform/vivid/vivid-tpg-colors.h @@ -61,8 +61,8 @@ enum tpg_color { extern const struct color tpg_colors[TPG_COLOR_MAX]; extern const unsigned short tpg_rec709_to_linear[255 * 16 + 1]; extern const unsigned short tpg_linear_to_rec709[255 * 16 + 1]; -extern const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1] - [V4L2_XFER_FUNC_NONE + 1] +extern const struct color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1] + [V4L2_XFER_FUNC_SMPTE2084 + 1] [TPG_COLOR_CSC_BLACK + 1]; #endif diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c index 1458c7955547..14256141f905 100644 --- a/drivers/media/platform/vivid/vivid-tpg.c +++ b/drivers/media/platform/vivid/vivid-tpg.c @@ -193,6 +193,14 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_SGBRG8: case V4L2_PIX_FMT_SGRBG8: case V4L2_PIX_FMT_SRGGB8: + case V4L2_PIX_FMT_SBGGR10: + case V4L2_PIX_FMT_SGBRG10: + case V4L2_PIX_FMT_SGRBG10: + case V4L2_PIX_FMT_SRGGB10: + case V4L2_PIX_FMT_SBGGR12: + case V4L2_PIX_FMT_SGBRG12: + case V4L2_PIX_FMT_SGRBG12: + case V4L2_PIX_FMT_SRGGB12: tpg->interleaved = true; tpg->vdownsampling[1] = 1; tpg->hdownsampling[1] = 1; @@ -349,6 +357,17 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) tpg->twopixelsize[0] = 2; tpg->twopixelsize[1] = 2; break; + case V4L2_PIX_FMT_SRGGB10: + case V4L2_PIX_FMT_SGRBG10: + case V4L2_PIX_FMT_SGBRG10: + case V4L2_PIX_FMT_SBGGR10: + case V4L2_PIX_FMT_SRGGB12: + case V4L2_PIX_FMT_SGRBG12: + case V4L2_PIX_FMT_SGBRG12: + case V4L2_PIX_FMT_SBGGR12: + tpg->twopixelsize[0] = 4; + tpg->twopixelsize[1] = 4; + break; case V4L2_PIX_FMT_YUV422P: case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: @@ -1112,6 +1131,70 @@ static void gen_twopix(struct tpg_data *tpg, buf[0][offset] = odd ? g_u : r_y; buf[1][offset] = odd ? b_v : g_u; break; + case V4L2_PIX_FMT_SBGGR10: + buf[0][offset] = odd ? g_u << 2 : b_v << 2; + buf[0][offset + 1] = odd ? g_u >> 6 : b_v >> 6; + buf[1][offset] = odd ? r_y << 2 : g_u << 2; + buf[1][offset + 1] = odd ? r_y >> 6 : g_u >> 6; + buf[0][offset] |= (buf[0][offset] >> 2) & 3; + buf[1][offset] |= (buf[1][offset] >> 2) & 3; + break; + case V4L2_PIX_FMT_SGBRG10: + buf[0][offset] = odd ? b_v << 2 : g_u << 2; + buf[0][offset + 1] = odd ? b_v >> 6 : g_u >> 6; + buf[1][offset] = odd ? g_u << 2 : r_y << 2; + buf[1][offset + 1] = odd ? g_u >> 6 : r_y >> 6; + buf[0][offset] |= (buf[0][offset] >> 2) & 3; + buf[1][offset] |= (buf[1][offset] >> 2) & 3; + break; + case V4L2_PIX_FMT_SGRBG10: + buf[0][offset] = odd ? r_y << 2 : g_u << 2; + buf[0][offset + 1] = odd ? r_y >> 6 : g_u >> 6; + buf[1][offset] = odd ? g_u << 2 : b_v << 2; + buf[1][offset + 1] = odd ? g_u >> 6 : b_v >> 6; + buf[0][offset] |= (buf[0][offset] >> 2) & 3; + buf[1][offset] |= (buf[1][offset] >> 2) & 3; + break; + case V4L2_PIX_FMT_SRGGB10: + buf[0][offset] = odd ? g_u << 2 : r_y << 2; + buf[0][offset + 1] = odd ? g_u >> 6 : r_y >> 6; + buf[1][offset] = odd ? b_v << 2 : g_u << 2; + buf[1][offset + 1] = odd ? b_v >> 6 : g_u >> 6; + buf[0][offset] |= (buf[0][offset] >> 2) & 3; + buf[1][offset] |= (buf[1][offset] >> 2) & 3; + break; + case V4L2_PIX_FMT_SBGGR12: + buf[0][offset] = odd ? g_u << 4 : b_v << 4; + buf[0][offset + 1] = odd ? g_u >> 4 : b_v >> 4; + buf[1][offset] = odd ? r_y << 4 : g_u << 4; + buf[1][offset + 1] = odd ? r_y >> 4 : g_u >> 4; + buf[0][offset] |= (buf[0][offset] >> 4) & 0xf; + buf[1][offset] |= (buf[1][offset] >> 4) & 0xf; + break; + case V4L2_PIX_FMT_SGBRG12: + buf[0][offset] = odd ? b_v << 4 : g_u << 4; + buf[0][offset + 1] = odd ? b_v >> 4 : g_u >> 4; + buf[1][offset] = odd ? g_u << 4 : r_y << 4; + buf[1][offset + 1] = odd ? g_u >> 4 : r_y >> 4; + buf[0][offset] |= (buf[0][offset] >> 4) & 0xf; + buf[1][offset] |= (buf[1][offset] >> 4) & 0xf; + break; + case V4L2_PIX_FMT_SGRBG12: + buf[0][offset] = odd ? r_y << 4 : g_u << 4; + buf[0][offset + 1] = odd ? r_y >> 4 : g_u >> 4; + buf[1][offset] = odd ? g_u << 4 : b_v << 4; + buf[1][offset + 1] = odd ? g_u >> 4 : b_v >> 4; + buf[0][offset] |= (buf[0][offset] >> 4) & 0xf; + buf[1][offset] |= (buf[1][offset] >> 4) & 0xf; + break; + case V4L2_PIX_FMT_SRGGB12: + buf[0][offset] = odd ? g_u << 4 : r_y << 4; + buf[0][offset + 1] = odd ? g_u >> 4 : r_y >> 4; + buf[1][offset] = odd ? b_v << 4 : g_u << 4; + buf[1][offset + 1] = odd ? b_v >> 4 : g_u >> 4; + buf[0][offset] |= (buf[0][offset] >> 4) & 0xf; + buf[1][offset] |= (buf[1][offset] >> 4) & 0xf; + break; } } @@ -1122,6 +1205,14 @@ unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line) case V4L2_PIX_FMT_SGBRG8: case V4L2_PIX_FMT_SGRBG8: case V4L2_PIX_FMT_SRGGB8: + case V4L2_PIX_FMT_SBGGR10: + case V4L2_PIX_FMT_SGBRG10: + case V4L2_PIX_FMT_SGRBG10: + case V4L2_PIX_FMT_SRGGB10: + case V4L2_PIX_FMT_SBGGR12: + case V4L2_PIX_FMT_SGBRG12: + case V4L2_PIX_FMT_SGRBG12: + case V4L2_PIX_FMT_SRGGB12: return buf_line & 1; default: return 0; diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c index ef81b01b53d2..e903d023e9df 100644 --- a/drivers/media/platform/vivid/vivid-vbi-cap.c +++ b/drivers/media/platform/vivid/vivid-vbi-cap.c @@ -94,36 +94,38 @@ static void vivid_g_fmt_vbi_cap(struct vivid_dev *dev, struct v4l2_vbi_format *v void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf) { struct v4l2_vbi_format vbi; - u8 *vbuf = vb2_plane_vaddr(&buf->vb, 0); + u8 *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); vivid_g_fmt_vbi_cap(dev, &vbi); - buf->vb.v4l2_buf.sequence = dev->vbi_cap_seq_count; + buf->vb.sequence = dev->vbi_cap_seq_count; if (dev->field_cap == V4L2_FIELD_ALTERNATE) - buf->vb.v4l2_buf.sequence /= 2; + buf->vb.sequence /= 2; - vivid_sliced_vbi_cap_fill(dev, buf->vb.v4l2_buf.sequence); + vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence); - memset(vbuf, 0x10, vb2_plane_size(&buf->vb, 0)); + memset(vbuf, 0x10, vb2_plane_size(&buf->vb.vb2_buf, 0)); if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode)) vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf); - v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); - buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset; + v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.timestamp.tv_sec += dev->time_wrap_offset; } -void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf) +void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, + struct vivid_buffer *buf) { - struct v4l2_sliced_vbi_data *vbuf = vb2_plane_vaddr(&buf->vb, 0); + struct v4l2_sliced_vbi_data *vbuf = + vb2_plane_vaddr(&buf->vb.vb2_buf, 0); - buf->vb.v4l2_buf.sequence = dev->vbi_cap_seq_count; + buf->vb.sequence = dev->vbi_cap_seq_count; if (dev->field_cap == V4L2_FIELD_ALTERNATE) - buf->vb.v4l2_buf.sequence /= 2; + buf->vb.sequence /= 2; - vivid_sliced_vbi_cap_fill(dev, buf->vb.v4l2_buf.sequence); + vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence); - memset(vbuf, 0, vb2_plane_size(&buf->vb, 0)); + memset(vbuf, 0, vb2_plane_size(&buf->vb.vb2_buf, 0)); if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode)) { unsigned i; @@ -131,11 +133,11 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *bu vbuf[i] = dev->vbi_gen.data[i]; } - v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); - buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset; + v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.timestamp.tv_sec += dev->time_wrap_offset; } -static int vbi_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int vbi_cap_queue_setup(struct vb2_queue *vq, const void *parg, unsigned *nbuffers, unsigned *nplanes, unsigned sizes[], void *alloc_ctxs[]) { @@ -187,8 +189,9 @@ static int vbi_cap_buf_prepare(struct vb2_buffer *vb) static void vbi_cap_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct vivid_buffer *buf = container_of(vb, struct vivid_buffer, vb); + struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb); dprintk(dev, 1, "%s\n", __func__); @@ -215,7 +218,8 @@ static int vbi_cap_start_streaming(struct vb2_queue *vq, unsigned count) list_for_each_entry_safe(buf, tmp, &dev->vbi_cap_active, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_QUEUED); } } return err; diff --git a/drivers/media/platform/vivid/vivid-vbi-out.c b/drivers/media/platform/vivid/vivid-vbi-out.c index 4e4c70e1e04a..75c5709f938e 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 struct v4l2_format *fmt, +static int vbi_out_queue_setup(struct vb2_queue *vq, const void *parg, unsigned *nbuffers, unsigned *nplanes, unsigned sizes[], void *alloc_ctxs[]) { @@ -79,8 +79,9 @@ static int vbi_out_buf_prepare(struct vb2_buffer *vb) static void vbi_out_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct vivid_buffer *buf = container_of(vb, struct vivid_buffer, vb); + struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb); dprintk(dev, 1, "%s\n", __func__); @@ -107,7 +108,8 @@ static int vbi_out_start_streaming(struct vb2_queue *vq, unsigned count) list_for_each_entry_safe(buf, tmp, &dev->vbi_out_active, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_QUEUED); } } return err; @@ -201,7 +203,8 @@ int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_forma return 0; } -int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) +int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh, + struct v4l2_format *fmt) { struct vivid_dev *dev = video_drvdata(file); struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced; @@ -217,10 +220,13 @@ int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format return 0; } -void vivid_sliced_vbi_out_process(struct vivid_dev *dev, struct vivid_buffer *buf) +void vivid_sliced_vbi_out_process(struct vivid_dev *dev, + struct vivid_buffer *buf) { - struct v4l2_sliced_vbi_data *vbi = vb2_plane_vaddr(&buf->vb, 0); - unsigned elems = vb2_get_plane_payload(&buf->vb, 0) / sizeof(*vbi); + struct v4l2_sliced_vbi_data *vbi = + vb2_plane_vaddr(&buf->vb.vb2_buf, 0); + unsigned elems = + vb2_get_plane_payload(&buf->vb.vb2_buf, 0) / sizeof(*vbi); dev->vbi_out_have_cc[0] = false; dev->vbi_out_have_cc[1] = false; diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c index ed0b8788a66f..ef5412311b2f 100644 --- a/drivers/media/platform/vivid/vivid-vid-cap.c +++ b/drivers/media/platform/vivid/vivid-vid-cap.c @@ -95,10 +95,11 @@ static const struct v4l2_discrete_probe webcam_probe = { VIVID_WEBCAM_SIZES }; -static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int vid_cap_queue_setup(struct vb2_queue *vq, const void *parg, 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; @@ -198,7 +199,7 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb) } vb2_set_plane_payload(vb, p, size); - vb->v4l2_planes[p].data_offset = dev->fmt_cap->data_offset[p]; + vb->planes[p].data_offset = dev->fmt_cap->data_offset[p]; } return 0; @@ -206,10 +207,11 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb) static void vid_cap_buf_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct v4l2_timecode *tc = &vb->v4l2_buf.timecode; + struct v4l2_timecode *tc = &vbuf->timecode; unsigned fps = 25; - unsigned seq = vb->v4l2_buf.sequence; + unsigned seq = vbuf->sequence; if (!vivid_is_sdtv_cap(dev)) return; @@ -218,7 +220,7 @@ static void vid_cap_buf_finish(struct vb2_buffer *vb) * Set the timecode. Rarely used, so it is interesting to * test this. */ - vb->v4l2_buf.flags |= V4L2_BUF_FLAG_TIMECODE; + vbuf->flags |= V4L2_BUF_FLAG_TIMECODE; if (dev->std_cap & V4L2_STD_525_60) fps = 30; tc->type = (fps == 30) ? V4L2_TC_TYPE_30FPS : V4L2_TC_TYPE_25FPS; @@ -231,8 +233,9 @@ static void vid_cap_buf_finish(struct vb2_buffer *vb) static void vid_cap_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct vivid_buffer *buf = container_of(vb, struct vivid_buffer, vb); + struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb); dprintk(dev, 1, "%s\n", __func__); @@ -268,7 +271,8 @@ static int vid_cap_start_streaming(struct vb2_queue *vq, unsigned count) list_for_each_entry_safe(buf, tmp, &dev->vid_cap_active, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_QUEUED); } } return err; diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c index fc73927a4abc..1678b730dba2 100644 --- a/drivers/media/platform/vivid/vivid-vid-common.c +++ b/drivers/media/platform/vivid/vivid-vid-common.c @@ -390,6 +390,62 @@ struct vivid_fmt vivid_formats[] = { .buffers = 1, }, { + .fourcc = V4L2_PIX_FMT_SBGGR10, /* Bayer BG/GR */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG10, /* Bayer GB/RG */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG10, /* Bayer GR/BG */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB10, /* Bayer RG/GB */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR12, /* Bayer BG/GR */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG12, /* Bayer GB/RG */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG12, /* Bayer GR/BG */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB12, /* Bayer RG/GB */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { .fourcc = V4L2_PIX_FMT_NV16M, .vdownsampling = { 1, 1 }, .bit_depth = { 8, 8 }, diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c index c404e275eae0..b77acb6a7013 100644 --- a/drivers/media/platform/vivid/vivid-vid-out.c +++ b/drivers/media/platform/vivid/vivid-vid-out.c @@ -31,10 +31,11 @@ #include "vivid-kthread-out.h" #include "vivid-vid-out.h" -static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int vid_out_queue_setup(struct vb2_queue *vq, const void *parg, 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; @@ -109,6 +110,7 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f static int vid_out_buf_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue); unsigned long size; unsigned planes; @@ -131,14 +133,14 @@ static int vid_out_buf_prepare(struct vb2_buffer *vb) } if (dev->field_out != V4L2_FIELD_ALTERNATE) - vb->v4l2_buf.field = dev->field_out; - else if (vb->v4l2_buf.field != V4L2_FIELD_TOP && - vb->v4l2_buf.field != V4L2_FIELD_BOTTOM) + vbuf->field = dev->field_out; + else if (vbuf->field != V4L2_FIELD_TOP && + vbuf->field != V4L2_FIELD_BOTTOM) return -EINVAL; for (p = 0; p < planes; p++) { size = dev->bytesperline_out[p] * dev->fmt_out_rect.height + - vb->v4l2_planes[p].data_offset; + vb->planes[p].data_offset; if (vb2_get_plane_payload(vb, p) < size) { dprintk(dev, 1, "%s the payload is too small for plane %u (%lu < %lu)\n", @@ -152,8 +154,9 @@ static int vid_out_buf_prepare(struct vb2_buffer *vb) static void vid_out_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct vivid_buffer *buf = container_of(vb, struct vivid_buffer, vb); + struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb); dprintk(dev, 1, "%s\n", __func__); @@ -186,7 +189,8 @@ static int vid_out_start_streaming(struct vb2_queue *vq, unsigned count) list_for_each_entry_safe(buf, tmp, &dev->vid_out_active, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_QUEUED); } } return err; diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 3294529a3108..cd5248a9a271 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -200,10 +200,10 @@ static void rpf_vdev_queue(struct vsp1_video *video, vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, buf->addr[0] + rpf->offsets[0]); - if (buf->buf.num_planes > 1) + if (buf->buf.vb2_buf.num_planes > 1) vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, buf->addr[1] + rpf->offsets[1]); - if (buf->buf.num_planes > 2) + if (buf->buf.vb2_buf.num_planes > 2) vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, buf->addr[2] + rpf->offsets[1]); } diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 3c124c14ce14..5ce88e1f5d71 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -24,7 +24,7 @@ #include <media/v4l2-fh.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-subdev.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "vsp1.h" @@ -610,11 +610,11 @@ vsp1_video_complete_buffer(struct vsp1_video *video) spin_unlock_irqrestore(&video->irqlock, flags); - done->buf.v4l2_buf.sequence = video->sequence++; - v4l2_get_timestamp(&done->buf.v4l2_buf.timestamp); - for (i = 0; i < done->buf.num_planes; ++i) - vb2_set_plane_payload(&done->buf, i, done->length[i]); - vb2_buffer_done(&done->buf, VB2_BUF_STATE_DONE); + done->buf.sequence = video->sequence++; + v4l2_get_timestamp(&done->buf.timestamp); + 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); return next; } @@ -787,10 +787,11 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1) */ static int -vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +vsp1_video_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 vsp1_video *video = vb2_get_drv_priv(vq); const struct v4l2_pix_format_mplane *format; struct v4l2_pix_format_mplane pix_mp; @@ -820,8 +821,9 @@ vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); - struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb); + struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vbuf); const struct v4l2_pix_format_mplane *format = &video->format; unsigned int i; @@ -841,9 +843,10 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) static void vsp1_video_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); - struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb); + struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vbuf); unsigned long flags; bool empty; @@ -954,7 +957,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq) /* Remove all buffers from the IRQ queue. */ spin_lock_irqsave(&video->irqlock, flags); list_for_each_entry(buffer, &video->irqqueue, queue) - vb2_buffer_done(&buffer->buf, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR); INIT_LIST_HEAD(&video->irqqueue); spin_unlock_irqrestore(&video->irqlock, flags); } diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index 0887a4d2742c..a929aa81cdbf 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -18,7 +18,7 @@ #include <linux/wait.h> #include <media/media-entity.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> struct vsp1_video; @@ -94,7 +94,7 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) } struct vsp1_video_buffer { - struct vb2_buffer buf; + struct vb2_v4l2_buffer buf; struct list_head queue; dma_addr_t addr[3]; @@ -102,9 +102,9 @@ struct vsp1_video_buffer { }; static inline struct vsp1_video_buffer * -to_vsp1_video_buffer(struct vb2_buffer *vb) +to_vsp1_video_buffer(struct vb2_v4l2_buffer *vbuf) { - return container_of(vb, struct vsp1_video_buffer, buf); + return container_of(vbuf, struct vsp1_video_buffer, buf); } struct vsp1_video_operations { diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 1d2b3a2f1573..95b62f4f77e7 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -201,9 +201,9 @@ static void wpf_vdev_queue(struct vsp1_video *video, struct vsp1_rwpf *wpf = container_of(video, struct vsp1_rwpf, video); vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, buf->addr[0]); - if (buf->buf.num_planes > 1) + if (buf->buf.vb2_buf.num_planes > 1) vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, buf->addr[1]); - if (buf->buf.num_planes > 2) + if (buf->buf.vb2_buf.num_planes > 2) vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, buf->addr[2]); } diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c index e779c93cb015..d11cc7072cd5 100644 --- a/drivers/media/platform/xilinx/xilinx-dma.c +++ b/drivers/media/platform/xilinx/xilinx-dma.c @@ -22,7 +22,7 @@ #include <media/v4l2-dev.h> #include <media/v4l2-fh.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "xilinx-dma.h" @@ -285,7 +285,7 @@ done: * @dma: DMA channel that uses the buffer */ struct xvip_dma_buffer { - struct vb2_buffer buf; + struct vb2_v4l2_buffer buf; struct list_head queue; struct xvip_dma *dma; }; @@ -301,18 +301,19 @@ static void xvip_dma_complete(void *param) list_del(&buf->queue); spin_unlock(&dma->queued_lock); - buf->buf.v4l2_buf.field = V4L2_FIELD_NONE; - buf->buf.v4l2_buf.sequence = dma->sequence++; - v4l2_get_timestamp(&buf->buf.v4l2_buf.timestamp); - vb2_set_plane_payload(&buf->buf, 0, dma->format.sizeimage); - vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE); + buf->buf.field = V4L2_FIELD_NONE; + buf->buf.sequence = dma->sequence++; + v4l2_get_timestamp(&buf->buf.timestamp); + 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 struct v4l2_format *fmt, +xvip_dma_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 xvip_dma *dma = vb2_get_drv_priv(vq); /* Make sure the image size is large enough. */ @@ -329,8 +330,9 @@ xvip_dma_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, static int xvip_dma_buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct xvip_dma *dma = vb2_get_drv_priv(vb->vb2_queue); - struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vb); + struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vbuf); buf->dma = dma; @@ -339,8 +341,9 @@ static int xvip_dma_buffer_prepare(struct vb2_buffer *vb) static void xvip_dma_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct xvip_dma *dma = vb2_get_drv_priv(vb->vb2_queue); - struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vb); + struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vbuf); struct dma_async_tx_descriptor *desc; dma_addr_t addr = vb2_dma_contig_plane_dma_addr(vb, 0); u32 flags; @@ -367,7 +370,7 @@ static void xvip_dma_buffer_queue(struct vb2_buffer *vb) desc = dmaengine_prep_interleaved_dma(dma->dma, &dma->xt, flags); if (!desc) { dev_err(dma->xdev->dev, "Failed to prepare DMA transfer\n"); - vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR); return; } desc->callback = xvip_dma_complete; @@ -434,7 +437,7 @@ error: /* Give back all queued buffers to videobuf2. */ spin_lock_irq(&dma->queued_lock); list_for_each_entry_safe(buf, nbuf, &dma->queued_bufs, queue) { - vb2_buffer_done(&buf->buf, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_QUEUED); list_del(&buf->queue); } spin_unlock_irq(&dma->queued_lock); @@ -461,7 +464,7 @@ static void xvip_dma_stop_streaming(struct vb2_queue *vq) /* Give back all queued buffers to videobuf2. */ spin_lock_irq(&dma->queued_lock); list_for_each_entry_safe(buf, nbuf, &dma->queued_bufs, queue) { - vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR); list_del(&buf->queue); } spin_unlock_irq(&dma->queued_lock); diff --git a/drivers/media/platform/xilinx/xilinx-dma.h b/drivers/media/platform/xilinx/xilinx-dma.h index a540111f8d3d..7a1621a2ef40 100644 --- a/drivers/media/platform/xilinx/xilinx-dma.h +++ b/drivers/media/platform/xilinx/xilinx-dma.h @@ -22,7 +22,7 @@ #include <media/media-entity.h> #include <media/v4l2-dev.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> struct dma_chan; struct xvip_composite_device; diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c index 1c087cb76815..d0549fba711c 100644 --- a/drivers/media/rc/ir-hix5hd2.c +++ b/drivers/media/rc/ir-hix5hd2.c @@ -257,7 +257,7 @@ static int hix5hd2_ir_probe(struct platform_device *pdev) goto clkerr; if (devm_request_irq(dev, priv->irq, hix5hd2_ir_rx_interrupt, - IRQF_NO_SUSPEND, pdev->name, priv) < 0) { + 0, pdev->name, priv) < 0) { dev_err(dev, "IRQ %d register failed\n", priv->irq); ret = -EINVAL; goto regerr; diff --git a/drivers/media/tuners/msi001.c b/drivers/media/tuners/msi001.c index b533240f8ec0..3a12ef35682b 100644 --- a/drivers/media/tuners/msi001.c +++ b/drivers/media/tuners/msi001.c @@ -513,7 +513,6 @@ MODULE_DEVICE_TABLE(spi, msi001_id_table); static struct spi_driver msi001_driver = { .driver = { .name = "msi001", - .owner = THIS_MODULE, .suppress_bind_attrs = true, }, .probe = msi001_probe, diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 507382160e5e..ce157edd45fa 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -166,6 +166,10 @@ static int si2157_init(struct dvb_frontend *fe) for (remaining = fw->size; remaining > 0; remaining -= 17) { len = fw->data[fw->size - remaining]; + if (len > SI2157_ARGLEN) { + dev_err(&client->dev, "Bad firmware length\n"); + goto err_release_firmware; + } memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); cmd.wlen = len; cmd.rlen = 1; diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c index 8f2e1c277c5f..fcbb49757614 100644 --- a/drivers/media/usb/airspy/airspy.c +++ b/drivers/media/usb/airspy/airspy.c @@ -21,6 +21,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> /* AirSpy USB API commands (from AirSpy Library) */ @@ -97,7 +98,8 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats); /* intermediate buffers with raw data from the USB device */ struct airspy_frame_buf { - struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ + /* common v4l buffer stuff -- must be first */ + struct vb2_v4l2_buffer vb; struct list_head list; }; @@ -310,13 +312,13 @@ static void airspy_urb_complete(struct urb *urb) } /* fill framebuffer */ - ptr = vb2_plane_vaddr(&fbuf->vb, 0); + ptr = vb2_plane_vaddr(&fbuf->vb.vb2_buf, 0); len = airspy_convert_stream(s, ptr, urb->transfer_buffer, urb->actual_length); - vb2_set_plane_payload(&fbuf->vb, 0, len); - v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp); - fbuf->vb.v4l2_buf.sequence = s->sequence++; - vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); + vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len); + v4l2_get_timestamp(&fbuf->vb.timestamp); + fbuf->vb.sequence = s->sequence++; + vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); } skip: usb_submit_urb(urb, GFP_ATOMIC); @@ -459,7 +461,7 @@ static void airspy_cleanup_queued_bufs(struct airspy *s) buf = list_entry(s->queued_bufs.next, struct airspy_frame_buf, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&s->queued_bufs_lock, flags); } @@ -486,7 +488,7 @@ static void airspy_disconnect(struct usb_interface *intf) /* Videobuf2 operations */ static int airspy_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, unsigned int *nbuffers, + const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { struct airspy *s = vb2_get_drv_priv(vq); @@ -505,14 +507,15 @@ static int airspy_queue_setup(struct vb2_queue *vq, static void airspy_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct airspy *s = vb2_get_drv_priv(vb->vb2_queue); struct airspy_frame_buf *buf = - container_of(vb, struct airspy_frame_buf, vb); + container_of(vbuf, struct airspy_frame_buf, vb); unsigned long flags; /* Check the device has not disconnected between prep and queuing */ if (unlikely(!s->udev)) { - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); return; } @@ -571,7 +574,8 @@ err_clear_bit: list_for_each_entry_safe(buf, tmp, &s->queued_bufs, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_QUEUED); } } diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c index f67247cf1a5a..130c8b49bf7f 100644 --- a/drivers/media/usb/au0828/au0828-vbi.c +++ b/drivers/media/usb/au0828/au0828-vbi.c @@ -30,10 +30,11 @@ /* ------------------------------------------------------------------ */ -static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int vbi_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 au0828_dev *dev = vb2_get_drv_priv(vq); unsigned long img_size = dev->vbi_width * dev->vbi_height * 2; unsigned long size; @@ -52,7 +53,6 @@ static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, static int vbi_buffer_prepare(struct vb2_buffer *vb) { struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); unsigned long size; size = dev->vbi_width * dev->vbi_height * 2; @@ -62,7 +62,7 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb) __func__, vb2_plane_size(vb, 0), size); return -EINVAL; } - vb2_set_plane_payload(&buf->vb, 0, size); + vb2_set_plane_payload(vb, 0, size); return 0; } @@ -71,7 +71,9 @@ static void vbi_buffer_queue(struct vb2_buffer *vb) { struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct au0828_buffer *buf = + container_of(vbuf, struct au0828_buffer, vb); struct au0828_dmaqueue *vbiq = &dev->vbiq; unsigned long flags = 0; diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 1a362a041ab3..45c622e234f7 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -302,20 +302,20 @@ static inline void buffer_filled(struct au0828_dev *dev, struct au0828_dmaqueue *dma_q, struct au0828_buffer *buf) { - struct vb2_buffer *vb = &buf->vb; - struct vb2_queue *q = vb->vb2_queue; + struct vb2_v4l2_buffer *vb = &buf->vb; + struct vb2_queue *q = vb->vb2_buf.vb2_queue; /* Advice that buffer was filled */ au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field); if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - vb->v4l2_buf.sequence = dev->frame_count++; + vb->sequence = dev->frame_count++; else - vb->v4l2_buf.sequence = dev->vbi_frame_count++; + vb->sequence = dev->vbi_frame_count++; - vb->v4l2_buf.field = V4L2_FIELD_INTERLACED; - v4l2_get_timestamp(&vb->v4l2_buf.timestamp); - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + vb->field = V4L2_FIELD_INTERLACED; + v4l2_get_timestamp(&vb->timestamp); + vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE); } /* @@ -531,11 +531,11 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) buf = dev->isoc_ctl.buf; if (buf != NULL) - outp = vb2_plane_vaddr(&buf->vb, 0); + outp = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); vbi_buf = dev->isoc_ctl.vbi_buf; if (vbi_buf != NULL) - vbioutp = vb2_plane_vaddr(&vbi_buf->vb, 0); + vbioutp = vb2_plane_vaddr(&vbi_buf->vb.vb2_buf, 0); for (i = 0; i < urb->number_of_packets; i++) { int status = urb->iso_frame_desc[i].status; @@ -574,7 +574,7 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) vbioutp = NULL; else vbioutp = vb2_plane_vaddr( - &vbi_buf->vb, 0); + &vbi_buf->vb.vb2_buf, 0); /* Video */ if (buf != NULL) @@ -583,7 +583,8 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) if (buf == NULL) outp = NULL; else - outp = vb2_plane_vaddr(&buf->vb, 0); + outp = vb2_plane_vaddr( + &buf->vb.vb2_buf, 0); /* As long as isoc traffic is arriving, keep resetting the timer */ @@ -637,10 +638,11 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) return rc; } -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int 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 au0828_dev *dev = vb2_get_drv_priv(vq); unsigned long img_size = dev->height * dev->bytesperline; unsigned long size; @@ -658,7 +660,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { - struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct au0828_buffer *buf = container_of(vbuf, + struct au0828_buffer, vb); struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue); buf->length = dev->height * dev->bytesperline; @@ -668,14 +672,15 @@ buffer_prepare(struct vb2_buffer *vb) __func__, vb2_plane_size(vb, 0), buf->length); return -EINVAL; } - vb2_set_plane_payload(&buf->vb, 0, buf->length); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->length); return 0; } static void buffer_queue(struct vb2_buffer *vb) { - struct au0828_buffer *buf = container_of(vb, + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct au0828_buffer *buf = container_of(vbuf, struct au0828_buffer, vb); struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue); @@ -826,14 +831,15 @@ static void au0828_stop_streaming(struct vb2_queue *vq) spin_lock_irqsave(&dev->slock, flags); if (dev->isoc_ctl.buf != NULL) { - vb2_buffer_done(&dev->isoc_ctl.buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&dev->isoc_ctl.buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); dev->isoc_ctl.buf = NULL; } while (!list_empty(&vidq->active)) { struct au0828_buffer *buf; buf = list_entry(vidq->active.next, struct au0828_buffer, list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); list_del(&buf->list); } spin_unlock_irqrestore(&dev->slock, flags); @@ -853,7 +859,7 @@ void au0828_stop_vbi_streaming(struct vb2_queue *vq) spin_lock_irqsave(&dev->slock, flags); if (dev->isoc_ctl.vbi_buf != NULL) { - vb2_buffer_done(&dev->isoc_ctl.vbi_buf->vb, + vb2_buffer_done(&dev->isoc_ctl.vbi_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); dev->isoc_ctl.vbi_buf = NULL; } @@ -862,7 +868,7 @@ void au0828_stop_vbi_streaming(struct vb2_queue *vq) buf = list_entry(vbiq->active.next, struct au0828_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); @@ -911,7 +917,7 @@ static void au0828_vid_buffer_timeout(unsigned long data) buf = dev->isoc_ctl.buf; if (buf != NULL) { - vid_data = vb2_plane_vaddr(&buf->vb, 0); + vid_data = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); memset(vid_data, 0x00, buf->length); /* Blank green frame */ buffer_filled(dev, dma_q, buf); } @@ -935,7 +941,7 @@ static void au0828_vbi_buffer_timeout(unsigned long data) buf = dev->isoc_ctl.vbi_buf; if (buf != NULL) { - vbi_data = vb2_plane_vaddr(&buf->vb, 0); + vbi_data = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); memset(vbi_data, 0x00, buf->length); buffer_filled(dev, dma_q, buf); } diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 3b480005ce3b..60b59391ea2a 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -28,6 +28,7 @@ /* Analog */ #include <linux/videodev2.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> @@ -167,7 +168,7 @@ struct au0828_usb_isoc_ctl { /* buffer for one video frame */ struct au0828_buffer { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; void *mem; diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 9798160698a3..d0d8f08e37c8 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -1114,7 +1114,8 @@ int cx231xx_enum_input(struct file *file, void *priv, struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; u32 gen_stat; - unsigned int ret, n; + unsigned int n; + int ret; n = i->index; if (n >= MAX_CX231XX_INPUT) diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 0376c092bab8..1dd962535f97 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -847,6 +847,10 @@ static const struct usb_device_id dvbsky_id_table[] = { USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI, &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI", RC_MAP_TT_1500) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, + USB_PID_TERRATEC_H7_3, + &dvbsky_t680c_props, "Terratec H7 Rev.4", + RC_MAP_TT_1500) }, { } }; MODULE_DEVICE_TABLE(usb, dvbsky_id_table); diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index c3cac4c12fb3..5a503a6bb8c5 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -34,6 +34,14 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) unsigned int pipe; u8 requesttype; + mutex_lock(&d->usb_mutex); + + if (req->size > sizeof(dev->buf)) { + dev_err(&d->intf->dev, "too large message %u\n", req->size); + ret = -EINVAL; + goto err_mutex_unlock; + } + if (req->index & CMD_WR_FLAG) { /* write */ memcpy(dev->buf, req->data, req->size); @@ -50,14 +58,17 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value, req->index, dev->buf, req->size); if (ret < 0) - goto err; + goto err_mutex_unlock; /* read request, copy returned data to return buf */ if (requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) memcpy(req->data, dev->buf, req->size); + mutex_unlock(&d->usb_mutex); + return 0; -err: +err_mutex_unlock: + mutex_unlock(&d->usb_mutex); dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -1885,6 +1896,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = { &rtl28xxu_props, "MSI DIGIVOX Micro HD", NULL) }, { DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620, &rtl28xxu_props, "Compro VideoMate U620F", NULL) }, + { DVB_USB_DEVICE(USB_VID_COMPRO, 0x0650, + &rtl28xxu_props, "Compro VideoMate U650F", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394, &rtl28xxu_props, "MaxMedia HU394-T", NULL) }, { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 9f6115a2ee01..138062960a73 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -71,7 +71,7 @@ struct rtl28xxu_dev { - u8 buf[28]; + u8 buf[128]; u8 chip_id; u8 tuner; char *tuner_name; diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c index 744e7ed743e1..e23c285b3108 100644 --- a/drivers/media/usb/em28xx/em28xx-vbi.c +++ b/drivers/media/usb/em28xx/em28xx-vbi.c @@ -31,10 +31,11 @@ /* ------------------------------------------------------------------ */ -static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int vbi_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 em28xx *dev = vb2_get_drv_priv(vq); struct em28xx_v4l2 *v4l2 = dev->v4l2; unsigned long size; @@ -61,7 +62,6 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb) { struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue); struct em28xx_v4l2 *v4l2 = dev->v4l2; - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); unsigned long size; size = v4l2->vbi_width * v4l2->vbi_height * 2; @@ -71,7 +71,7 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb) __func__, vb2_plane_size(vb, 0), size); return -EINVAL; } - vb2_set_plane_payload(&buf->vb, 0, size); + vb2_set_plane_payload(vb, 0, size); return 0; } @@ -79,8 +79,10 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb) static void vbi_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue); - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); + struct em28xx_buffer *buf = + container_of(vbuf, struct em28xx_buffer, vb); struct em28xx_dmaqueue *vbiq = &dev->vbiq; unsigned long flags = 0; diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 4397ce5e78df..6a3cf342e087 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -433,14 +433,14 @@ static inline void finish_buffer(struct em28xx *dev, { em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field); - buf->vb.v4l2_buf.sequence = dev->v4l2->field_count++; + buf->vb.sequence = dev->v4l2->field_count++; if (dev->v4l2->progressive) - buf->vb.v4l2_buf.field = V4L2_FIELD_NONE; + buf->vb.field = V4L2_FIELD_NONE; else - buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; - v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + buf->vb.field = V4L2_FIELD_INTERLACED; + v4l2_get_timestamp(&buf->vb.timestamp); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } /* @@ -871,10 +871,11 @@ static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type) Videobuf2 operations ------------------------------------------------------------------*/ -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int 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 em28xx *dev = vb2_get_drv_priv(vq); struct em28xx_v4l2 *v4l2 = dev->v4l2; unsigned long size; @@ -900,12 +901,12 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue); struct em28xx_v4l2 *v4l2 = dev->v4l2; - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); unsigned long size; - em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field); + em28xx_videodbg("%s, field=%d\n", __func__, vbuf->field); size = (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3; @@ -914,7 +915,7 @@ buffer_prepare(struct vb2_buffer *vb) __func__, vb2_plane_size(vb, 0), size); return -EINVAL; } - vb2_set_plane_payload(&buf->vb, 0, size); + vb2_set_plane_payload(vb, 0, size); return 0; } @@ -924,6 +925,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) struct em28xx *dev = vb2_get_drv_priv(vq); struct em28xx_v4l2 *v4l2 = dev->v4l2; struct v4l2_frequency f; + struct v4l2_fh *owner; int rc = 0; em28xx_videodbg("%s\n", __func__); @@ -964,7 +966,8 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) /* Ask tuner to go to analog or radio mode */ memset(&f, 0, sizeof(f)); f.frequency = v4l2->frequency; - if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO) + owner = (struct v4l2_fh *)vq->owner; + if (owner && owner->vdev->vfl_type == VFL_TYPE_RADIO) f.type = V4L2_TUNER_RADIO; else f.type = V4L2_TUNER_ANALOG_TV; @@ -995,7 +998,8 @@ static void em28xx_stop_streaming(struct vb2_queue *vq) spin_lock_irqsave(&dev->slock, flags); if (dev->usb_ctl.vid_buf != NULL) { - vb2_buffer_done(&dev->usb_ctl.vid_buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&dev->usb_ctl.vid_buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); dev->usb_ctl.vid_buf = NULL; } while (!list_empty(&vidq->active)) { @@ -1003,7 +1007,7 @@ static void em28xx_stop_streaming(struct vb2_queue *vq) buf = list_entry(vidq->active.next, struct em28xx_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); } @@ -1026,7 +1030,8 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq) spin_lock_irqsave(&dev->slock, flags); if (dev->usb_ctl.vbi_buf != NULL) { - vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); dev->usb_ctl.vbi_buf = NULL; } while (!list_empty(&vbiq->active)) { @@ -1034,7 +1039,7 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq) buf = list_entry(vbiq->active.next, struct em28xx_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->slock, flags); } @@ -1042,8 +1047,10 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq) static void buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue); - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); + struct em28xx_buffer *buf = + container_of(vbuf, struct em28xx_buffer, vb); struct em28xx_dmaqueue *vidq = &dev->vidq; unsigned long flags = 0; diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index e6559c6f143c..76bf8ba372b3 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -35,6 +35,7 @@ #include <linux/kref.h> #include <linux/videodev2.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> @@ -264,7 +265,7 @@ struct em28xx_fmt { /* buffer for one video frame */ struct em28xx_buffer { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; void *mem; diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c index 0ab81ec8897a..ae1cfa792c58 100644 --- a/drivers/media/usb/go7007/go7007-driver.c +++ b/drivers/media/usb/go7007/go7007-driver.c @@ -386,10 +386,10 @@ start_error: */ static inline void store_byte(struct go7007_buffer *vb, u8 byte) { - if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) { - u8 *ptr = vb2_plane_vaddr(&vb->vb, 0); + if (vb && vb->vb.vb2_buf.planes[0].bytesused < GO7007_BUF_SIZE) { + u8 *ptr = vb2_plane_vaddr(&vb->vb.vb2_buf, 0); - ptr[vb->vb.v4l2_planes[0].bytesused++] = byte; + ptr[vb->vb.vb2_buf.planes[0].bytesused++] = byte; } } @@ -401,7 +401,7 @@ static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *v .type = V4L2_EVENT_MOTION_DET, .u.motion_det = { .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ, - .frame_sequence = vb->vb.v4l2_buf.sequence, + .frame_sequence = vb->vb.sequence, .region_mask = motion_regions, }, }; @@ -417,7 +417,7 @@ static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *v */ static void go7007_motion_regions(struct go7007 *go, struct go7007_buffer *vb) { - u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused; + u32 *bytesused = &vb->vb.vb2_buf.planes[0].bytesused; unsigned motion[4] = { 0, 0, 0, 0 }; u32 motion_regions = 0; unsigned stride = (go->width + 7) >> 3; @@ -458,25 +458,26 @@ static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buf go->next_seq++; return vb; } - bytesused = &vb->vb.v4l2_planes[0].bytesused; + bytesused = &vb->vb.vb2_buf.planes[0].bytesused; - vb->vb.v4l2_buf.sequence = go->next_seq++; + vb->vb.sequence = go->next_seq++; if (vb->modet_active && *bytesused + 216 < GO7007_BUF_SIZE) go7007_motion_regions(go, vb); else go7007_set_motion_regions(go, vb, 0); - v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp); + v4l2_get_timestamp(&vb->vb.timestamp); vb_tmp = vb; spin_lock(&go->spinlock); list_del(&vb->list); if (list_empty(&go->vidq_active)) vb = NULL; else - vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list); + vb = list_first_entry(&go->vidq_active, + struct go7007_buffer, list); go->active_buf = vb; spin_unlock(&go->spinlock); - vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&vb_tmp->vb.vb2_buf, VB2_BUF_STATE_DONE); return vb; } @@ -519,9 +520,10 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) } for (i = 0; i < length; ++i) { - if (vb && vb->vb.v4l2_planes[0].bytesused >= GO7007_BUF_SIZE - 3) { + if (vb && vb->vb.vb2_buf.planes[0].bytesused >= + GO7007_BUF_SIZE - 3) { v4l2_info(&go->v4l2_dev, "dropping oversized frame\n"); - vb->vb.v4l2_planes[0].bytesused = 0; + vb->vb.vb2_buf.planes[0].bytesused = 0; vb->frame_offset = 0; vb->modet_active = 0; vb = go->active_buf = NULL; @@ -601,7 +603,8 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) vb = frame_boundary(go, vb); go->seen_frame = buf[i] == frame_start_code; if (vb && go->seen_frame) - vb->frame_offset = vb->vb.v4l2_planes[0].bytesused; + vb->frame_offset = + vb->vb.vb2_buf.planes[0].bytesused; } /* Handle any special chunk types, or just write the * start code to the (potentially new) buffer */ diff --git a/drivers/media/usb/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c index 5f4c9b9e899a..60bf5f0644d1 100644 --- a/drivers/media/usb/go7007/go7007-fw.c +++ b/drivers/media/usb/go7007/go7007-fw.c @@ -379,7 +379,7 @@ static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space) buf = kzalloc(4096, GFP_KERNEL); if (buf == NULL) - return -1; + return -ENOMEM; for (i = 1; i < 32; ++i) { mjpeg_frame_header(go, buf + size, i); @@ -646,7 +646,7 @@ static int gen_mpeg1hdr_to_package(struct go7007 *go, buf = kzalloc(5120, GFP_KERNEL); if (buf == NULL) - return -1; + return -ENOMEM; framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME); if (go->interlace_coding) @@ -832,7 +832,7 @@ static int gen_mpeg4hdr_to_package(struct go7007 *go, buf = kzalloc(5120, GFP_KERNEL); if (buf == NULL) - return -1; + return -ENOMEM; framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME); i = 368; diff --git a/drivers/media/usb/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h index 2251c3f99d1d..745185eb060b 100644 --- a/drivers/media/usb/go7007/go7007-priv.h +++ b/drivers/media/usb/go7007/go7007-priv.h @@ -20,7 +20,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-fh.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> struct go7007; @@ -136,7 +136,7 @@ struct go7007_hpi_ops { #define GO7007_BUF_SIZE (GO7007_BUF_PAGES << PAGE_SHIFT) struct go7007_buffer { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; unsigned int frame_offset; u32 modet_active; diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c index c57207e268c3..f3d187db9368 100644 --- a/drivers/media/usb/go7007/go7007-v4l2.c +++ b/drivers/media/usb/go7007/go7007-v4l2.c @@ -52,7 +52,7 @@ static bool valid_pixelformat(u32 pixelformat) static u32 get_frame_type_flag(struct go7007_buffer *vb, int format) { - u8 *ptr = vb2_plane_vaddr(&vb->vb, 0); + u8 *ptr = vb2_plane_vaddr(&vb->vb.vb2_buf, 0); switch (format) { case V4L2_PIX_FMT_MJPEG: @@ -369,7 +369,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, } static int go7007_queue_setup(struct vb2_queue *q, - const struct v4l2_format *fmt, + const void *parg, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -386,8 +386,9 @@ static void go7007_buf_queue(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; struct go7007 *go = vb2_get_drv_priv(vq); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct go7007_buffer *go7007_vb = - container_of(vb, struct go7007_buffer, vb); + container_of(vbuf, struct go7007_buffer, vb); unsigned long flags; spin_lock_irqsave(&go->spinlock, flags); @@ -397,12 +398,13 @@ static void go7007_buf_queue(struct vb2_buffer *vb) static int go7007_buf_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct go7007_buffer *go7007_vb = - container_of(vb, struct go7007_buffer, vb); + container_of(vbuf, struct go7007_buffer, vb); go7007_vb->modet_active = 0; go7007_vb->frame_offset = 0; - vb->v4l2_planes[0].bytesused = 0; + vb->planes[0].bytesused = 0; return 0; } @@ -410,15 +412,15 @@ static void go7007_buf_finish(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; struct go7007 *go = vb2_get_drv_priv(vq); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct go7007_buffer *go7007_vb = - container_of(vb, struct go7007_buffer, vb); + container_of(vbuf, struct go7007_buffer, vb); u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format); - struct v4l2_buffer *buf = &vb->v4l2_buf; - buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME | + vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME | V4L2_BUF_FLAG_PFRAME); - buf->flags |= frame_type_flag; - buf->field = V4L2_FIELD_NONE; + vbuf->flags |= frame_type_flag; + vbuf->field = V4L2_FIELD_NONE; } static int go7007_start_streaming(struct vb2_queue *q, unsigned int count) diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index e54cee856a80..af5cd8213e8b 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -436,7 +436,7 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, } j = gspca_dev->fr_queue[i]; frame = &gspca_dev->frame[j]; - frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get()); + v4l2_get_timestamp(&frame->v4l2_buf.timestamp); frame->v4l2_buf.sequence = gspca_dev->sequence++; gspca_dev->image = frame->data; gspca_dev->image_len = 0; @@ -1909,7 +1909,7 @@ static ssize_t dev_read(struct file *file, char __user *data, } /* get a frame */ - timestamp = ktime_to_timeval(ktime_get()); + v4l2_get_timestamp(×tamp); timestamp.tv_sec--; n = 2; for (;;) { diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c index fd1fa412e094..e05bfec90f46 100644 --- a/drivers/media/usb/hackrf/hackrf.c +++ b/drivers/media/usb/hackrf/hackrf.c @@ -21,6 +21,7 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> /* HackRF USB API commands (from HackRF Library) */ @@ -31,8 +32,10 @@ enum { CMD_BOARD_ID_READ = 0x0e, CMD_VERSION_STRING_READ = 0x0f, CMD_SET_FREQ = 0x10, + CMD_AMP_ENABLE = 0x11, CMD_SET_LNA_GAIN = 0x13, CMD_SET_VGA_GAIN = 0x14, + CMD_SET_TXVGA_GAIN = 0x15, }; /* @@ -43,10 +46,10 @@ enum { #define MAX_BULK_BUFS (6) #define BULK_BUFFER_SIZE (128 * 512) -static const struct v4l2_frequency_band bands_adc[] = { +static const struct v4l2_frequency_band bands_adc_dac[] = { { .tuner = 0, - .type = V4L2_TUNER_ADC, + .type = V4L2_TUNER_SDR, .index = 0, .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, .rangelow = 200000, @@ -54,7 +57,7 @@ static const struct v4l2_frequency_band bands_adc[] = { }, }; -static const struct v4l2_frequency_band bands_rf[] = { +static const struct v4l2_frequency_band bands_rx_tx[] = { { .tuner = 1, .type = V4L2_TUNER_RF, @@ -67,7 +70,6 @@ static const struct v4l2_frequency_band bands_rf[] = { /* stream formats */ struct hackrf_format { - char *name; u32 pixelformat; u32 buffersize; }; @@ -75,7 +77,6 @@ struct hackrf_format { /* format descriptions for capture and preview */ static struct hackrf_format formats[] = { { - .name = "Complex S8", .pixelformat = V4L2_SDR_FMT_CS8, .buffersize = BULK_BUFFER_SIZE, }, @@ -84,28 +85,44 @@ static struct hackrf_format formats[] = { static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats); /* intermediate buffers with raw data from the USB device */ -struct hackrf_frame_buf { - struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ +struct hackrf_buffer { + struct vb2_v4l2_buffer vb; struct list_head list; }; struct hackrf_dev { -#define POWER_ON (1 << 1) -#define URB_BUF (1 << 2) -#define USB_STATE_URB_BUF (1 << 3) +#define USB_STATE_URB_BUF 1 /* XXX: set manually */ +#define RX_ON 4 +#define TX_ON 5 +#define RX_ADC_FREQUENCY 11 +#define TX_DAC_FREQUENCY 12 +#define RX_BANDWIDTH 13 +#define TX_BANDWIDTH 14 +#define RX_RF_FREQUENCY 15 +#define TX_RF_FREQUENCY 16 +#define RX_RF_GAIN 17 +#define TX_RF_GAIN 18 +#define RX_IF_GAIN 19 +#define RX_LNA_GAIN 20 +#define TX_LNA_GAIN 21 unsigned long flags; + struct usb_interface *intf; struct device *dev; struct usb_device *udev; - struct video_device vdev; + struct video_device rx_vdev; + struct video_device tx_vdev; struct v4l2_device v4l2_dev; /* videobuf2 queue and queued buffers list */ - struct vb2_queue vb_queue; - struct list_head queued_bufs; - spinlock_t queued_bufs_lock; /* Protects queued_bufs */ + struct vb2_queue rx_vb2_queue; + struct vb2_queue tx_vb2_queue; + struct list_head rx_buffer_list; + struct list_head tx_buffer_list; + spinlock_t buffer_list_lock; /* Protects buffer_list */ unsigned sequence; /* Buffer sequence counter */ unsigned int vb_full; /* vb is full and packets dropped */ + unsigned int vb_empty; /* vb is empty and packets dropped */ /* Note if taking both locks v4l2_lock must always be locked first! */ struct mutex v4l2_lock; /* Protects everything else */ @@ -125,16 +142,24 @@ struct hackrf_dev { /* Current configuration */ unsigned int f_adc; - unsigned int f_rf; + unsigned int f_dac; + unsigned int f_rx; + unsigned int f_tx; u32 pixelformat; u32 buffersize; /* Controls */ - struct v4l2_ctrl_handler hdl; - struct v4l2_ctrl *bandwidth_auto; - struct v4l2_ctrl *bandwidth; - struct v4l2_ctrl *lna_gain; - struct v4l2_ctrl *if_gain; + struct v4l2_ctrl_handler rx_ctrl_handler; + struct v4l2_ctrl *rx_bandwidth_auto; + struct v4l2_ctrl *rx_bandwidth; + struct v4l2_ctrl *rx_rf_gain; + struct v4l2_ctrl *rx_lna_gain; + struct v4l2_ctrl *rx_if_gain; + struct v4l2_ctrl_handler tx_ctrl_handler; + struct v4l2_ctrl *tx_bandwidth_auto; + struct v4l2_ctrl *tx_bandwidth; + struct v4l2_ctrl *tx_rf_gain; + struct v4l2_ctrl *tx_lna_gain; /* Sample rate calc */ unsigned long jiffies_next; @@ -164,6 +189,7 @@ static int hackrf_ctrl_msg(struct hackrf_dev *dev, u8 request, u16 value, switch (request) { case CMD_SET_TRANSCEIVER_MODE: case CMD_SET_FREQ: + case CMD_AMP_ENABLE: case CMD_SAMPLE_RATE_SET: case CMD_BASEBAND_FILTER_BANDWIDTH_SET: pipe = usb_sndctrlpipe(dev->udev, 0); @@ -173,6 +199,7 @@ static int hackrf_ctrl_msg(struct hackrf_dev *dev, u8 request, u16 value, case CMD_VERSION_STRING_READ: case CMD_SET_LNA_GAIN: case CMD_SET_VGA_GAIN: + case CMD_SET_TXVGA_GAIN: pipe = usb_rcvctrlpipe(dev->udev, 0); requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); break; @@ -205,25 +232,227 @@ err: return ret; } +static int hackrf_set_params(struct hackrf_dev *dev) +{ + struct usb_interface *intf = dev->intf; + int ret, i; + u8 buf[8], u8tmp; + unsigned int uitmp, uitmp1, uitmp2; + const bool rx = test_bit(RX_ON, &dev->flags); + const bool tx = test_bit(TX_ON, &dev->flags); + static const struct { + u32 freq; + } bandwidth_lut[] = { + { 1750000}, /* 1.75 MHz */ + { 2500000}, /* 2.5 MHz */ + { 3500000}, /* 3.5 MHz */ + { 5000000}, /* 5 MHz */ + { 5500000}, /* 5.5 MHz */ + { 6000000}, /* 6 MHz */ + { 7000000}, /* 7 MHz */ + { 8000000}, /* 8 MHz */ + { 9000000}, /* 9 MHz */ + {10000000}, /* 10 MHz */ + {12000000}, /* 12 MHz */ + {14000000}, /* 14 MHz */ + {15000000}, /* 15 MHz */ + {20000000}, /* 20 MHz */ + {24000000}, /* 24 MHz */ + {28000000}, /* 28 MHz */ + }; + + if (!rx && !tx) { + dev_dbg(&intf->dev, "device is sleeping\n"); + return 0; + } + + /* ADC / DAC frequency */ + if (rx && test_and_clear_bit(RX_ADC_FREQUENCY, &dev->flags)) { + dev_dbg(&intf->dev, "RX ADC frequency=%u Hz\n", dev->f_adc); + uitmp1 = dev->f_adc; + uitmp2 = 1; + set_bit(TX_DAC_FREQUENCY, &dev->flags); + } else if (tx && test_and_clear_bit(TX_DAC_FREQUENCY, &dev->flags)) { + dev_dbg(&intf->dev, "TX DAC frequency=%u Hz\n", dev->f_dac); + uitmp1 = dev->f_dac; + uitmp2 = 1; + set_bit(RX_ADC_FREQUENCY, &dev->flags); + } else { + uitmp1 = uitmp2 = 0; + } + if (uitmp1 || uitmp2) { + buf[0] = (uitmp1 >> 0) & 0xff; + buf[1] = (uitmp1 >> 8) & 0xff; + buf[2] = (uitmp1 >> 16) & 0xff; + buf[3] = (uitmp1 >> 24) & 0xff; + buf[4] = (uitmp2 >> 0) & 0xff; + buf[5] = (uitmp2 >> 8) & 0xff; + buf[6] = (uitmp2 >> 16) & 0xff; + buf[7] = (uitmp2 >> 24) & 0xff; + ret = hackrf_ctrl_msg(dev, CMD_SAMPLE_RATE_SET, 0, 0, buf, 8); + if (ret) + goto err; + } + + /* bandwidth */ + if (rx && test_and_clear_bit(RX_BANDWIDTH, &dev->flags)) { + if (dev->rx_bandwidth_auto->val == true) + uitmp = dev->f_adc; + else + uitmp = dev->rx_bandwidth->val; + + for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) { + if (uitmp <= bandwidth_lut[i].freq) { + uitmp = bandwidth_lut[i].freq; + break; + } + } + dev->rx_bandwidth->val = uitmp; + dev->rx_bandwidth->cur.val = uitmp; + dev_dbg(&intf->dev, "RX bandwidth selected=%u\n", uitmp); + set_bit(TX_BANDWIDTH, &dev->flags); + } else if (tx && test_and_clear_bit(TX_BANDWIDTH, &dev->flags)) { + if (dev->tx_bandwidth_auto->val == true) + uitmp = dev->f_dac; + else + uitmp = dev->tx_bandwidth->val; + + for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) { + if (uitmp <= bandwidth_lut[i].freq) { + uitmp = bandwidth_lut[i].freq; + break; + } + } + dev->tx_bandwidth->val = uitmp; + dev->tx_bandwidth->cur.val = uitmp; + dev_dbg(&intf->dev, "TX bandwidth selected=%u\n", uitmp); + set_bit(RX_BANDWIDTH, &dev->flags); + } else { + uitmp = 0; + } + if (uitmp) { + uitmp1 = uitmp2 = 0; + uitmp1 |= ((uitmp >> 0) & 0xff) << 0; + uitmp1 |= ((uitmp >> 8) & 0xff) << 8; + uitmp2 |= ((uitmp >> 16) & 0xff) << 0; + uitmp2 |= ((uitmp >> 24) & 0xff) << 8; + ret = hackrf_ctrl_msg(dev, CMD_BASEBAND_FILTER_BANDWIDTH_SET, + uitmp1, uitmp2, NULL, 0); + if (ret) + goto err; + } + + /* RX / TX RF frequency */ + if (rx && test_and_clear_bit(RX_RF_FREQUENCY, &dev->flags)) { + dev_dbg(&intf->dev, "RX RF frequency=%u Hz\n", dev->f_rx); + uitmp1 = dev->f_rx / 1000000; + uitmp2 = dev->f_rx % 1000000; + set_bit(TX_RF_FREQUENCY, &dev->flags); + } else if (tx && test_and_clear_bit(TX_RF_FREQUENCY, &dev->flags)) { + dev_dbg(&intf->dev, "TX RF frequency=%u Hz\n", dev->f_tx); + uitmp1 = dev->f_tx / 1000000; + uitmp2 = dev->f_tx % 1000000; + set_bit(RX_RF_FREQUENCY, &dev->flags); + } else { + uitmp1 = uitmp2 = 0; + } + if (uitmp1 || uitmp2) { + buf[0] = (uitmp1 >> 0) & 0xff; + buf[1] = (uitmp1 >> 8) & 0xff; + buf[2] = (uitmp1 >> 16) & 0xff; + buf[3] = (uitmp1 >> 24) & 0xff; + buf[4] = (uitmp2 >> 0) & 0xff; + buf[5] = (uitmp2 >> 8) & 0xff; + buf[6] = (uitmp2 >> 16) & 0xff; + buf[7] = (uitmp2 >> 24) & 0xff; + ret = hackrf_ctrl_msg(dev, CMD_SET_FREQ, 0, 0, buf, 8); + if (ret) + goto err; + } + + /* RX RF gain */ + if (rx && test_and_clear_bit(RX_RF_GAIN, &dev->flags)) { + dev_dbg(&intf->dev, "RX RF gain val=%d->%d\n", + dev->rx_rf_gain->cur.val, dev->rx_rf_gain->val); + + u8tmp = (dev->rx_rf_gain->val) ? 1 : 0; + ret = hackrf_ctrl_msg(dev, CMD_AMP_ENABLE, u8tmp, 0, NULL, 0); + if (ret) + goto err; + set_bit(TX_RF_GAIN, &dev->flags); + } + + /* TX RF gain */ + if (tx && test_and_clear_bit(TX_RF_GAIN, &dev->flags)) { + dev_dbg(&intf->dev, "TX RF gain val=%d->%d\n", + dev->tx_rf_gain->cur.val, dev->tx_rf_gain->val); + + u8tmp = (dev->tx_rf_gain->val) ? 1 : 0; + ret = hackrf_ctrl_msg(dev, CMD_AMP_ENABLE, u8tmp, 0, NULL, 0); + if (ret) + goto err; + set_bit(RX_RF_GAIN, &dev->flags); + } + + /* RX LNA gain */ + if (rx && test_and_clear_bit(RX_LNA_GAIN, &dev->flags)) { + dev_dbg(dev->dev, "RX LNA gain val=%d->%d\n", + dev->rx_lna_gain->cur.val, dev->rx_lna_gain->val); + + ret = hackrf_ctrl_msg(dev, CMD_SET_LNA_GAIN, 0, + dev->rx_lna_gain->val, &u8tmp, 1); + if (ret) + goto err; + } + + /* RX IF gain */ + if (rx && test_and_clear_bit(RX_IF_GAIN, &dev->flags)) { + dev_dbg(&intf->dev, "IF gain val=%d->%d\n", + dev->rx_if_gain->cur.val, dev->rx_if_gain->val); + + ret = hackrf_ctrl_msg(dev, CMD_SET_VGA_GAIN, 0, + dev->rx_if_gain->val, &u8tmp, 1); + if (ret) + goto err; + } + + /* TX LNA gain */ + if (tx && test_and_clear_bit(TX_LNA_GAIN, &dev->flags)) { + dev_dbg(&intf->dev, "TX LNA gain val=%d->%d\n", + dev->tx_lna_gain->cur.val, dev->tx_lna_gain->val); + + ret = hackrf_ctrl_msg(dev, CMD_SET_TXVGA_GAIN, 0, + dev->tx_lna_gain->val, &u8tmp, 1); + if (ret) + goto err; + } + + return 0; +err: + dev_dbg(&intf->dev, "failed=%d\n", ret); + return ret; +} + /* Private functions */ -static struct hackrf_frame_buf *hackrf_get_next_fill_buf(struct hackrf_dev *dev) +static struct hackrf_buffer *hackrf_get_next_buffer(struct hackrf_dev *dev, + struct list_head *buffer_list) { unsigned long flags; - struct hackrf_frame_buf *buf = NULL; + struct hackrf_buffer *buffer = NULL; - spin_lock_irqsave(&dev->queued_bufs_lock, flags); - if (list_empty(&dev->queued_bufs)) + spin_lock_irqsave(&dev->buffer_list_lock, flags); + if (list_empty(buffer_list)) goto leave; - buf = list_entry(dev->queued_bufs.next, struct hackrf_frame_buf, list); - list_del(&buf->list); + buffer = list_entry(buffer_list->next, struct hackrf_buffer, list); + list_del(&buffer->list); leave: - spin_unlock_irqrestore(&dev->queued_bufs_lock, flags); - return buf; + spin_unlock_irqrestore(&dev->buffer_list_lock, flags); + return buffer; } -static unsigned int hackrf_convert_stream(struct hackrf_dev *dev, - void *dst, void *src, unsigned int src_len) +static void hackrf_copy_stream(struct hackrf_dev *dev, void *dst, void *src, + unsigned int src_len) { memcpy(dst, src, src_len); @@ -243,22 +472,21 @@ static unsigned int hackrf_convert_stream(struct hackrf_dev *dev, /* total number of samples */ dev->sample += src_len / 2; - - return src_len; } /* * This gets called for the bulk stream pipe. This is done in interrupt * time, so it has to be fast, not crash, and not stall. Neat. */ -static void hackrf_urb_complete(struct urb *urb) +static void hackrf_urb_complete_in(struct urb *urb) { struct hackrf_dev *dev = urb->context; - struct hackrf_frame_buf *fbuf; + struct usb_interface *intf = dev->intf; + struct hackrf_buffer *buffer; + unsigned int len; - dev_dbg_ratelimited(dev->dev, "status=%d length=%d/%d errors=%d\n", - urb->status, urb->actual_length, - urb->transfer_buffer_length, urb->error_count); + dev_dbg_ratelimited(&intf->dev, "status=%d length=%u/%u\n", urb->status, + urb->actual_length, urb->transfer_buffer_length); switch (urb->status) { case 0: /* success */ @@ -269,33 +497,74 @@ static void hackrf_urb_complete(struct urb *urb) case -ESHUTDOWN: return; default: /* error */ - dev_err_ratelimited(dev->dev, "URB failed %d\n", urb->status); - break; + dev_err_ratelimited(&intf->dev, "URB failed %d\n", urb->status); + goto exit_usb_submit_urb; } - if (likely(urb->actual_length > 0)) { - void *ptr; - unsigned int len; - /* get free framebuffer */ - fbuf = hackrf_get_next_fill_buf(dev); - if (unlikely(fbuf == NULL)) { - dev->vb_full++; - dev_notice_ratelimited(dev->dev, - "videobuf is full, %d packets dropped\n", - dev->vb_full); - goto skip; - } + /* get buffer to write */ + buffer = hackrf_get_next_buffer(dev, &dev->rx_buffer_list); + if (unlikely(buffer == NULL)) { + dev->vb_full++; + dev_notice_ratelimited(&intf->dev, + "buffer is full - %u packets dropped\n", + dev->vb_full); + goto exit_usb_submit_urb; + } + + len = min_t(unsigned long, vb2_plane_size(&buffer->vb.vb2_buf, 0), + urb->actual_length); + hackrf_copy_stream(dev, vb2_plane_vaddr(&buffer->vb.vb2_buf, 0), + 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); + vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_DONE); +exit_usb_submit_urb: + usb_submit_urb(urb, GFP_ATOMIC); +} + +static void hackrf_urb_complete_out(struct urb *urb) +{ + struct hackrf_dev *dev = urb->context; + struct usb_interface *intf = dev->intf; + struct hackrf_buffer *buffer; + unsigned int len; + + dev_dbg_ratelimited(&intf->dev, "status=%d length=%u/%u\n", urb->status, + urb->actual_length, urb->transfer_buffer_length); + + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + dev_err_ratelimited(&intf->dev, "URB failed %d\n", urb->status); + } - /* fill framebuffer */ - ptr = vb2_plane_vaddr(&fbuf->vb, 0); - len = hackrf_convert_stream(dev, ptr, urb->transfer_buffer, - urb->actual_length); - vb2_set_plane_payload(&fbuf->vb, 0, len); - v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp); - fbuf->vb.v4l2_buf.sequence = dev->sequence++; - vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); + /* get buffer to read */ + buffer = hackrf_get_next_buffer(dev, &dev->tx_buffer_list); + if (unlikely(buffer == NULL)) { + dev->vb_empty++; + dev_notice_ratelimited(&intf->dev, + "buffer is empty - %u packets dropped\n", + dev->vb_empty); + urb->actual_length = 0; + goto exit_usb_submit_urb; } -skip: + + len = min_t(unsigned long, urb->transfer_buffer_length, + vb2_get_plane_payload(&buffer->vb.vb2_buf, 0)); + hackrf_copy_stream(dev, urb->transfer_buffer, + vb2_plane_vaddr(&buffer->vb.vb2_buf, 0), len); + urb->actual_length = len; + buffer->vb.sequence = dev->sequence++; + v4l2_get_timestamp(&buffer->vb.timestamp); + vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_DONE); +exit_usb_submit_urb: usb_submit_urb(urb, GFP_ATOMIC); } @@ -394,9 +663,19 @@ static int hackrf_free_urbs(struct hackrf_dev *dev) return 0; } -static int hackrf_alloc_urbs(struct hackrf_dev *dev) +static int hackrf_alloc_urbs(struct hackrf_dev *dev, bool rcv) { int i, j; + unsigned int pipe; + usb_complete_t complete; + + if (rcv) { + pipe = usb_rcvbulkpipe(dev->udev, 0x81); + complete = &hackrf_urb_complete_in; + } else { + pipe = usb_sndbulkpipe(dev->udev, 0x02); + complete = &hackrf_urb_complete_out; + } /* allocate the URBs */ for (i = 0; i < MAX_BULK_BUFS; i++) { @@ -410,10 +689,10 @@ static int hackrf_alloc_urbs(struct hackrf_dev *dev) } usb_fill_bulk_urb(dev->urb_list[i], dev->udev, - usb_rcvbulkpipe(dev->udev, 0x81), + pipe, dev->buf_list[i], BULK_BUFFER_SIZE, - hackrf_urb_complete, dev); + complete, dev); dev->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; dev->urb_list[i]->transfer_dma = dev->dma_addr[i]; @@ -423,25 +702,6 @@ static int hackrf_alloc_urbs(struct hackrf_dev *dev) return 0; } -/* Must be called with vb_queue_lock hold */ -static void hackrf_cleanup_queued_bufs(struct hackrf_dev *dev) -{ - unsigned long flags; - - dev_dbg(dev->dev, "\n"); - - spin_lock_irqsave(&dev->queued_bufs_lock, flags); - while (!list_empty(&dev->queued_bufs)) { - struct hackrf_frame_buf *buf; - - buf = list_entry(dev->queued_bufs.next, - struct hackrf_frame_buf, list); - list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - } - spin_unlock_irqrestore(&dev->queued_bufs_lock, flags); -} - /* The user yanked out the cable... */ static void hackrf_disconnect(struct usb_interface *intf) { @@ -455,7 +715,8 @@ static void hackrf_disconnect(struct usb_interface *intf) /* No need to keep the urbs around after disconnection */ dev->udev = NULL; v4l2_device_disconnect(&dev->v4l2_dev); - video_unregister_device(&dev->vdev); + video_unregister_device(&dev->tx_vdev); + video_unregister_device(&dev->rx_vdev); mutex_unlock(&dev->v4l2_lock); mutex_unlock(&dev->vb_queue_lock); @@ -463,8 +724,33 @@ static void hackrf_disconnect(struct usb_interface *intf) } /* Videobuf2 operations */ +static void hackrf_return_all_buffers(struct vb2_queue *vq, + enum vb2_buffer_state state) +{ + struct hackrf_dev *dev = vb2_get_drv_priv(vq); + struct usb_interface *intf = dev->intf; + struct hackrf_buffer *buffer, *node; + struct list_head *buffer_list; + unsigned long flags; + + dev_dbg(&intf->dev, "\n"); + + if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE) + buffer_list = &dev->rx_buffer_list; + else + buffer_list = &dev->tx_buffer_list; + + spin_lock_irqsave(&dev->buffer_list_lock, flags); + list_for_each_entry_safe(buffer, node, buffer_list, list) { + dev_dbg(&intf->dev, "list_for_each_entry_safe\n"); + vb2_buffer_done(&buffer->vb.vb2_buf, state); + list_del(&buffer->list); + } + spin_unlock_irqrestore(&dev->buffer_list_lock, flags); +} + static int hackrf_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, unsigned int *nbuffers, + const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { struct hackrf_dev *dev = vb2_get_drv_priv(vq); @@ -483,37 +769,62 @@ static int hackrf_queue_setup(struct vb2_queue *vq, static void hackrf_buf_queue(struct vb2_buffer *vb) { - struct hackrf_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct hackrf_frame_buf *buf = - container_of(vb, struct hackrf_frame_buf, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct vb2_queue *vq = vb->vb2_queue; + struct hackrf_dev *dev = vb2_get_drv_priv(vq); + struct hackrf_buffer *buffer = container_of(vbuf, struct hackrf_buffer, vb); + struct list_head *buffer_list; unsigned long flags; - spin_lock_irqsave(&dev->queued_bufs_lock, flags); - list_add_tail(&buf->list, &dev->queued_bufs); - spin_unlock_irqrestore(&dev->queued_bufs_lock, flags); + dev_dbg_ratelimited(&dev->intf->dev, "\n"); + + if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE) + buffer_list = &dev->rx_buffer_list; + else + buffer_list = &dev->tx_buffer_list; + + spin_lock_irqsave(&dev->buffer_list_lock, flags); + list_add_tail(&buffer->list, buffer_list); + spin_unlock_irqrestore(&dev->buffer_list_lock, flags); } static int hackrf_start_streaming(struct vb2_queue *vq, unsigned int count) { struct hackrf_dev *dev = vb2_get_drv_priv(vq); + struct usb_interface *intf = dev->intf; int ret; + unsigned int mode; - dev_dbg(dev->dev, "\n"); - - if (!dev->udev) - return -ENODEV; + dev_dbg(&intf->dev, "count=%i\n", count); mutex_lock(&dev->v4l2_lock); - dev->sequence = 0; + /* Allow only RX or TX, not both same time */ + if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE) { + if (test_bit(TX_ON, &dev->flags)) { + ret = -EBUSY; + goto err_hackrf_return_all_buffers; + } + + mode = 1; + set_bit(RX_ON, &dev->flags); + } else { + if (test_bit(RX_ON, &dev->flags)) { + ret = -EBUSY; + goto err_hackrf_return_all_buffers; + } + + mode = 2; + set_bit(TX_ON, &dev->flags); + } - set_bit(POWER_ON, &dev->flags); + dev->sequence = 0; ret = hackrf_alloc_stream_bufs(dev); if (ret) goto err; - ret = hackrf_alloc_urbs(dev); + ret = hackrf_alloc_urbs(dev, (mode == 1)); if (ret) goto err; @@ -521,39 +832,37 @@ static int hackrf_start_streaming(struct vb2_queue *vq, unsigned int count) if (ret) goto err; + ret = hackrf_set_params(dev); + if (ret) + goto err; + /* start hardware streaming */ - ret = hackrf_ctrl_msg(dev, CMD_SET_TRANSCEIVER_MODE, 1, 0, NULL, 0); + ret = hackrf_ctrl_msg(dev, CMD_SET_TRANSCEIVER_MODE, mode, 0, NULL, 0); if (ret) goto err; - goto exit_mutex_unlock; + mutex_unlock(&dev->v4l2_lock); + + return 0; err: hackrf_kill_urbs(dev); hackrf_free_urbs(dev); hackrf_free_stream_bufs(dev); - clear_bit(POWER_ON, &dev->flags); - - /* return all queued buffers to vb2 */ - { - struct hackrf_frame_buf *buf, *tmp; - - list_for_each_entry_safe(buf, tmp, &dev->queued_bufs, list) { - list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); - } - } - -exit_mutex_unlock: + clear_bit(RX_ON, &dev->flags); + clear_bit(TX_ON, &dev->flags); +err_hackrf_return_all_buffers: + hackrf_return_all_buffers(vq, VB2_BUF_STATE_QUEUED); mutex_unlock(&dev->v4l2_lock); - + dev_dbg(&intf->dev, "failed=%d\n", ret); return ret; } static void hackrf_stop_streaming(struct vb2_queue *vq) { struct hackrf_dev *dev = vb2_get_drv_priv(vq); + struct usb_interface *intf = dev->intf; - dev_dbg(dev->dev, "\n"); + dev_dbg(&intf->dev, "\n"); mutex_lock(&dev->v4l2_lock); @@ -564,9 +873,12 @@ static void hackrf_stop_streaming(struct vb2_queue *vq) hackrf_free_urbs(dev); hackrf_free_stream_bufs(dev); - hackrf_cleanup_queued_bufs(dev); + hackrf_return_all_buffers(vq, VB2_BUF_STATE_ERROR); - clear_bit(POWER_ON, &dev->flags); + if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE) + clear_bit(RX_ON, &dev->flags); + else + clear_bit(TX_ON, &dev->flags); mutex_unlock(&dev->v4l2_lock); } @@ -584,29 +896,46 @@ static int hackrf_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { struct hackrf_dev *dev = video_drvdata(file); + struct usb_interface *intf = dev->intf; + struct video_device *vdev = video_devdata(file); - dev_dbg(dev->dev, "\n"); + dev_dbg(&intf->dev, "\n"); + + if (vdev->vfl_dir == VFL_DIR_RX) + cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER | + V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; + else + cap->device_caps = V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR | + V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; + + cap->capabilities = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER | + V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR | + V4L2_CAP_STREAMING | V4L2_CAP_READWRITE | + V4L2_CAP_DEVICE_CAPS; strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, dev->vdev.name, sizeof(cap->card)); + strlcpy(cap->card, dev->rx_vdev.name, sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE | V4L2_CAP_TUNER; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } -static int hackrf_s_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_format *f) +static int hackrf_s_fmt_sdr(struct file *file, void *priv, + struct v4l2_format *f) { struct hackrf_dev *dev = video_drvdata(file); - struct vb2_queue *q = &dev->vb_queue; + struct video_device *vdev = video_devdata(file); + struct vb2_queue *q; int i; dev_dbg(dev->dev, "pixelformat fourcc %4.4s\n", (char *)&f->fmt.sdr.pixelformat); + if (vdev->vfl_dir == VFL_DIR_RX) + q = &dev->rx_vb2_queue; + else + q = &dev->tx_vb2_queue; + if (vb2_is_busy(q)) return -EBUSY; @@ -628,8 +957,8 @@ static int hackrf_s_fmt_sdr_cap(struct file *file, void *priv, return 0; } -static int hackrf_g_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_format *f) +static int hackrf_g_fmt_sdr(struct file *file, void *priv, + struct v4l2_format *f) { struct hackrf_dev *dev = video_drvdata(file); @@ -643,8 +972,8 @@ static int hackrf_g_fmt_sdr_cap(struct file *file, void *priv, return 0; } -static int hackrf_try_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_format *f) +static int hackrf_try_fmt_sdr(struct file *file, void *priv, + struct v4l2_format *f) { struct hackrf_dev *dev = video_drvdata(file); int i; @@ -666,8 +995,8 @@ static int hackrf_try_fmt_sdr_cap(struct file *file, void *priv, return 0; } -static int hackrf_enum_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) +static int hackrf_enum_fmt_sdr(struct file *file, void *priv, + struct v4l2_fmtdesc *f) { struct hackrf_dev *dev = video_drvdata(file); @@ -676,7 +1005,6 @@ static int hackrf_enum_fmt_sdr_cap(struct file *file, void *priv, if (f->index >= NUM_FORMATS) return -EINVAL; - strlcpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].pixelformat; return 0; @@ -709,17 +1037,56 @@ static int hackrf_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) if (v->index == 0) { strlcpy(v->name, "HackRF ADC", sizeof(v->name)); - v->type = V4L2_TUNER_ADC; + v->type = V4L2_TUNER_SDR; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; - v->rangelow = bands_adc[0].rangelow; - v->rangehigh = bands_adc[0].rangehigh; + v->rangelow = bands_adc_dac[0].rangelow; + v->rangehigh = bands_adc_dac[0].rangehigh; ret = 0; } else if (v->index == 1) { strlcpy(v->name, "HackRF RF", sizeof(v->name)); v->type = V4L2_TUNER_RF; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; - v->rangelow = bands_rf[0].rangelow; - v->rangehigh = bands_rf[0].rangehigh; + v->rangelow = bands_rx_tx[0].rangelow; + v->rangehigh = bands_rx_tx[0].rangehigh; + ret = 0; + } else { + ret = -EINVAL; + } + + return ret; +} + +static int hackrf_s_modulator(struct file *file, void *fh, + const struct v4l2_modulator *a) +{ + struct hackrf_dev *dev = video_drvdata(file); + + dev_dbg(dev->dev, "index=%d\n", a->index); + + return a->index > 1 ? -EINVAL : 0; +} + +static int hackrf_g_modulator(struct file *file, void *fh, + struct v4l2_modulator *a) +{ + struct hackrf_dev *dev = video_drvdata(file); + int ret; + + dev_dbg(dev->dev, "index=%d\n", a->index); + + if (a->index == 0) { + strlcpy(a->name, "HackRF DAC", sizeof(a->name)); + a->type = V4L2_TUNER_SDR; + a->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; + a->rangelow = bands_adc_dac[0].rangelow; + a->rangehigh = bands_adc_dac[0].rangehigh; + ret = 0; + } else if (a->index == 1) { + strlcpy(a->name, "HackRF RF", sizeof(a->name)); + a->type = V4L2_TUNER_RF; + a->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; + a->rangelow = bands_rx_tx[0].rangelow; + a->rangehigh = bands_rx_tx[0].rangehigh; ret = 0; } else { ret = -EINVAL; @@ -732,47 +1099,46 @@ static int hackrf_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { struct hackrf_dev *dev = video_drvdata(file); + struct usb_interface *intf = dev->intf; + struct video_device *vdev = video_devdata(file); int ret; - unsigned int upper, lower; - u8 buf[8]; + unsigned int uitmp; - dev_dbg(dev->dev, "tuner=%d type=%d frequency=%u\n", + dev_dbg(&intf->dev, "tuner=%d type=%d frequency=%u\n", f->tuner, f->type, f->frequency); if (f->tuner == 0) { - dev->f_adc = clamp_t(unsigned int, f->frequency, - bands_adc[0].rangelow, bands_adc[0].rangehigh); - dev_dbg(dev->dev, "ADC frequency=%u Hz\n", dev->f_adc); - upper = dev->f_adc; - lower = 1; - buf[0] = (upper >> 0) & 0xff; - buf[1] = (upper >> 8) & 0xff; - buf[2] = (upper >> 16) & 0xff; - buf[3] = (upper >> 24) & 0xff; - buf[4] = (lower >> 0) & 0xff; - buf[5] = (lower >> 8) & 0xff; - buf[6] = (lower >> 16) & 0xff; - buf[7] = (lower >> 24) & 0xff; - ret = hackrf_ctrl_msg(dev, CMD_SAMPLE_RATE_SET, 0, 0, buf, 8); + uitmp = clamp(f->frequency, bands_adc_dac[0].rangelow, + bands_adc_dac[0].rangehigh); + if (vdev->vfl_dir == VFL_DIR_RX) { + dev->f_adc = uitmp; + set_bit(RX_ADC_FREQUENCY, &dev->flags); + } else { + dev->f_dac = uitmp; + set_bit(TX_DAC_FREQUENCY, &dev->flags); + } } else if (f->tuner == 1) { - dev->f_rf = clamp_t(unsigned int, f->frequency, - bands_rf[0].rangelow, bands_rf[0].rangehigh); - dev_dbg(dev->dev, "RF frequency=%u Hz\n", dev->f_rf); - upper = dev->f_rf / 1000000; - lower = dev->f_rf % 1000000; - buf[0] = (upper >> 0) & 0xff; - buf[1] = (upper >> 8) & 0xff; - buf[2] = (upper >> 16) & 0xff; - buf[3] = (upper >> 24) & 0xff; - buf[4] = (lower >> 0) & 0xff; - buf[5] = (lower >> 8) & 0xff; - buf[6] = (lower >> 16) & 0xff; - buf[7] = (lower >> 24) & 0xff; - ret = hackrf_ctrl_msg(dev, CMD_SET_FREQ, 0, 0, buf, 8); + uitmp = clamp(f->frequency, bands_rx_tx[0].rangelow, + bands_rx_tx[0].rangehigh); + if (vdev->vfl_dir == VFL_DIR_RX) { + dev->f_rx = uitmp; + set_bit(RX_RF_FREQUENCY, &dev->flags); + } else { + dev->f_tx = uitmp; + set_bit(TX_RF_FREQUENCY, &dev->flags); + } } else { ret = -EINVAL; + goto err; } + ret = hackrf_set_params(dev); + if (ret) + goto err; + + return 0; +err: + dev_dbg(&intf->dev, "failed=%d\n", ret); return ret; } @@ -780,22 +1146,32 @@ static int hackrf_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct hackrf_dev *dev = video_drvdata(file); + struct usb_interface *intf = dev->intf; + struct video_device *vdev = video_devdata(file); int ret; dev_dbg(dev->dev, "tuner=%d type=%d\n", f->tuner, f->type); if (f->tuner == 0) { - f->type = V4L2_TUNER_ADC; - f->frequency = dev->f_adc; - ret = 0; + f->type = V4L2_TUNER_SDR; + if (vdev->vfl_dir == VFL_DIR_RX) + f->frequency = dev->f_adc; + else + f->frequency = dev->f_dac; } else if (f->tuner == 1) { f->type = V4L2_TUNER_RF; - f->frequency = dev->f_rf; - ret = 0; + if (vdev->vfl_dir == VFL_DIR_RX) + f->frequency = dev->f_rx; + else + f->frequency = dev->f_tx; } else { ret = -EINVAL; + goto err; } + return 0; +err: + dev_dbg(&intf->dev, "failed=%d\n", ret); return ret; } @@ -809,17 +1185,17 @@ static int hackrf_enum_freq_bands(struct file *file, void *priv, band->tuner, band->type, band->index); if (band->tuner == 0) { - if (band->index >= ARRAY_SIZE(bands_adc)) { + if (band->index >= ARRAY_SIZE(bands_adc_dac)) { ret = -EINVAL; } else { - *band = bands_adc[band->index]; + *band = bands_adc_dac[band->index]; ret = 0; } } else if (band->tuner == 1) { - if (band->index >= ARRAY_SIZE(bands_rf)) { + if (band->index >= ARRAY_SIZE(bands_rx_tx)) { ret = -EINVAL; } else { - *band = bands_rf[band->index]; + *band = bands_rx_tx[band->index]; ret = 0; } } else { @@ -832,10 +1208,15 @@ static int hackrf_enum_freq_bands(struct file *file, void *priv, static const struct v4l2_ioctl_ops hackrf_ioctl_ops = { .vidioc_querycap = hackrf_querycap, - .vidioc_s_fmt_sdr_cap = hackrf_s_fmt_sdr_cap, - .vidioc_g_fmt_sdr_cap = hackrf_g_fmt_sdr_cap, - .vidioc_enum_fmt_sdr_cap = hackrf_enum_fmt_sdr_cap, - .vidioc_try_fmt_sdr_cap = hackrf_try_fmt_sdr_cap, + .vidioc_s_fmt_sdr_cap = hackrf_s_fmt_sdr, + .vidioc_g_fmt_sdr_cap = hackrf_g_fmt_sdr, + .vidioc_enum_fmt_sdr_cap = hackrf_enum_fmt_sdr, + .vidioc_try_fmt_sdr_cap = hackrf_try_fmt_sdr, + + .vidioc_s_fmt_sdr_out = hackrf_s_fmt_sdr, + .vidioc_g_fmt_sdr_out = hackrf_g_fmt_sdr, + .vidioc_enum_fmt_sdr_out = hackrf_enum_fmt_sdr, + .vidioc_try_fmt_sdr_out = hackrf_try_fmt_sdr, .vidioc_reqbufs = vb2_ioctl_reqbufs, .vidioc_create_bufs = vb2_ioctl_create_bufs, @@ -843,6 +1224,7 @@ static const struct v4l2_ioctl_ops hackrf_ioctl_ops = { .vidioc_querybuf = vb2_ioctl_querybuf, .vidioc_qbuf = vb2_ioctl_qbuf, .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, .vidioc_streamon = vb2_ioctl_streamon, .vidioc_streamoff = vb2_ioctl_streamoff, @@ -850,6 +1232,9 @@ static const struct v4l2_ioctl_ops hackrf_ioctl_ops = { .vidioc_s_tuner = hackrf_s_tuner, .vidioc_g_tuner = hackrf_g_tuner, + .vidioc_s_modulator = hackrf_s_modulator, + .vidioc_g_modulator = hackrf_g_modulator, + .vidioc_s_frequency = hackrf_s_frequency, .vidioc_g_frequency = hackrf_g_frequency, .vidioc_enum_freq_bands = hackrf_enum_freq_bands, @@ -864,6 +1249,7 @@ static const struct v4l2_file_operations hackrf_fops = { .open = v4l2_fh_open, .release = vb2_fop_release, .read = vb2_fop_read, + .write = vb2_fop_write, .poll = vb2_fop_poll, .mmap = vb2_fop_mmap, .unlocked_ioctl = video_ioctl2, @@ -880,135 +1266,93 @@ static void hackrf_video_release(struct v4l2_device *v) { struct hackrf_dev *dev = container_of(v, struct hackrf_dev, v4l2_dev); - v4l2_ctrl_handler_free(&dev->hdl); + dev_dbg(dev->dev, "\n"); + + v4l2_ctrl_handler_free(&dev->rx_ctrl_handler); + v4l2_ctrl_handler_free(&dev->tx_ctrl_handler); v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); } -static int hackrf_set_bandwidth(struct hackrf_dev *dev) -{ - int ret, i; - u16 u16tmp, u16tmp2; - unsigned int bandwidth; - - static const struct { - u32 freq; - } bandwidth_lut[] = { - { 1750000}, /* 1.75 MHz */ - { 2500000}, /* 2.5 MHz */ - { 3500000}, /* 3.5 MHz */ - { 5000000}, /* 5 MHz */ - { 5500000}, /* 5.5 MHz */ - { 6000000}, /* 6 MHz */ - { 7000000}, /* 7 MHz */ - { 8000000}, /* 8 MHz */ - { 9000000}, /* 9 MHz */ - {10000000}, /* 10 MHz */ - {12000000}, /* 12 MHz */ - {14000000}, /* 14 MHz */ - {15000000}, /* 15 MHz */ - {20000000}, /* 20 MHz */ - {24000000}, /* 24 MHz */ - {28000000}, /* 28 MHz */ - }; - - dev_dbg(dev->dev, "bandwidth auto=%d->%d val=%d->%d f_adc=%u\n", - dev->bandwidth_auto->cur.val, - dev->bandwidth_auto->val, dev->bandwidth->cur.val, - dev->bandwidth->val, dev->f_adc); - - if (dev->bandwidth_auto->val == true) - bandwidth = dev->f_adc; - else - bandwidth = dev->bandwidth->val; - - for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) { - if (bandwidth <= bandwidth_lut[i].freq) { - bandwidth = bandwidth_lut[i].freq; - break; - } - } - - dev->bandwidth->val = bandwidth; - dev->bandwidth->cur.val = bandwidth; - - dev_dbg(dev->dev, "bandwidth selected=%d\n", bandwidth); - - u16tmp = 0; - u16tmp |= ((bandwidth >> 0) & 0xff) << 0; - u16tmp |= ((bandwidth >> 8) & 0xff) << 8; - u16tmp2 = 0; - u16tmp2 |= ((bandwidth >> 16) & 0xff) << 0; - u16tmp2 |= ((bandwidth >> 24) & 0xff) << 8; - - ret = hackrf_ctrl_msg(dev, CMD_BASEBAND_FILTER_BANDWIDTH_SET, - u16tmp, u16tmp2, NULL, 0); - if (ret) - dev_dbg(dev->dev, "failed=%d\n", ret); - - return ret; -} - -static int hackrf_set_lna_gain(struct hackrf_dev *dev) -{ - int ret; - u8 u8tmp; - - dev_dbg(dev->dev, "lna val=%d->%d\n", - dev->lna_gain->cur.val, dev->lna_gain->val); - - ret = hackrf_ctrl_msg(dev, CMD_SET_LNA_GAIN, 0, dev->lna_gain->val, - &u8tmp, 1); - if (ret) - dev_dbg(dev->dev, "failed=%d\n", ret); - - return ret; -} - -static int hackrf_set_if_gain(struct hackrf_dev *dev) +static int hackrf_s_ctrl_rx(struct v4l2_ctrl *ctrl) { + struct hackrf_dev *dev = container_of(ctrl->handler, + struct hackrf_dev, rx_ctrl_handler); + struct usb_interface *intf = dev->intf; int ret; - u8 u8tmp; - dev_dbg(dev->dev, "val=%d->%d\n", - dev->if_gain->cur.val, dev->if_gain->val); + switch (ctrl->id) { + case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO: + case V4L2_CID_RF_TUNER_BANDWIDTH: + set_bit(RX_BANDWIDTH, &dev->flags); + break; + case V4L2_CID_RF_TUNER_RF_GAIN: + set_bit(RX_RF_GAIN, &dev->flags); + break; + case V4L2_CID_RF_TUNER_LNA_GAIN: + set_bit(RX_LNA_GAIN, &dev->flags); + break; + case V4L2_CID_RF_TUNER_IF_GAIN: + set_bit(RX_IF_GAIN, &dev->flags); + break; + default: + dev_dbg(&intf->dev, "unknown ctrl: id=%d name=%s\n", + ctrl->id, ctrl->name); + ret = -EINVAL; + goto err; + } - ret = hackrf_ctrl_msg(dev, CMD_SET_VGA_GAIN, 0, dev->if_gain->val, - &u8tmp, 1); + ret = hackrf_set_params(dev); if (ret) - dev_dbg(dev->dev, "failed=%d\n", ret); + goto err; + return 0; +err: + dev_dbg(&intf->dev, "failed=%d\n", ret); return ret; } -static int hackrf_s_ctrl(struct v4l2_ctrl *ctrl) +static int hackrf_s_ctrl_tx(struct v4l2_ctrl *ctrl) { struct hackrf_dev *dev = container_of(ctrl->handler, - struct hackrf_dev, hdl); + struct hackrf_dev, tx_ctrl_handler); + struct usb_interface *intf = dev->intf; int ret; switch (ctrl->id) { case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO: case V4L2_CID_RF_TUNER_BANDWIDTH: - ret = hackrf_set_bandwidth(dev); + set_bit(TX_BANDWIDTH, &dev->flags); break; case V4L2_CID_RF_TUNER_LNA_GAIN: - ret = hackrf_set_lna_gain(dev); + set_bit(TX_LNA_GAIN, &dev->flags); break; - case V4L2_CID_RF_TUNER_IF_GAIN: - ret = hackrf_set_if_gain(dev); + case V4L2_CID_RF_TUNER_RF_GAIN: + set_bit(TX_RF_GAIN, &dev->flags); break; default: - dev_dbg(dev->dev, "unknown ctrl: id=%d name=%s\n", - ctrl->id, ctrl->name); + dev_dbg(&intf->dev, "unknown ctrl: id=%d name=%s\n", + ctrl->id, ctrl->name); ret = -EINVAL; + goto err; } + ret = hackrf_set_params(dev); + if (ret) + goto err; + + return 0; +err: + dev_dbg(&intf->dev, "failed=%d\n", ret); return ret; } -static const struct v4l2_ctrl_ops hackrf_ctrl_ops = { - .s_ctrl = hackrf_s_ctrl, +static const struct v4l2_ctrl_ops hackrf_ctrl_ops_rx = { + .s_ctrl = hackrf_s_ctrl_rx, +}; + +static const struct v4l2_ctrl_ops hackrf_ctrl_ops_tx = { + .s_ctrl = hackrf_s_ctrl_tx, }; static int hackrf_probe(struct usb_interface *intf, @@ -1019,19 +1363,29 @@ static int hackrf_probe(struct usb_interface *intf, u8 u8tmp, buf[BUF_SIZE]; dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) - return -ENOMEM; + if (!dev) { + ret = -ENOMEM; + goto err; + } mutex_init(&dev->v4l2_lock); mutex_init(&dev->vb_queue_lock); - spin_lock_init(&dev->queued_bufs_lock); - INIT_LIST_HEAD(&dev->queued_bufs); + spin_lock_init(&dev->buffer_list_lock); + INIT_LIST_HEAD(&dev->rx_buffer_list); + INIT_LIST_HEAD(&dev->tx_buffer_list); + dev->intf = intf; dev->dev = &intf->dev; dev->udev = interface_to_usbdev(intf); - dev->f_adc = bands_adc[0].rangelow; - dev->f_rf = bands_rf[0].rangelow; dev->pixelformat = formats[0].pixelformat; dev->buffersize = formats[0].buffersize; + dev->f_adc = bands_adc_dac[0].rangelow; + dev->f_dac = bands_adc_dac[0].rangelow; + dev->f_rx = bands_rx_tx[0].rangelow; + dev->f_tx = bands_rx_tx[0].rangelow; + set_bit(RX_ADC_FREQUENCY, &dev->flags); + set_bit(TX_DAC_FREQUENCY, &dev->flags); + set_bit(RX_RF_FREQUENCY, &dev->flags); + set_bit(TX_RF_FREQUENCY, &dev->flags); /* Detect device */ ret = hackrf_ctrl_msg(dev, CMD_BOARD_ID_READ, 0, 0, &u8tmp, 1); @@ -1040,83 +1394,143 @@ static int hackrf_probe(struct usb_interface *intf, buf, BUF_SIZE); if (ret) { dev_err(dev->dev, "Could not detect board\n"); - goto err_free_mem; + goto err_kfree; } buf[BUF_SIZE - 1] = '\0'; - dev_info(dev->dev, "Board ID: %02x\n", u8tmp); dev_info(dev->dev, "Firmware version: %s\n", buf); - /* Init videobuf2 queue structure */ - dev->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE; - dev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; - dev->vb_queue.drv_priv = dev; - dev->vb_queue.buf_struct_size = sizeof(struct hackrf_frame_buf); - dev->vb_queue.ops = &hackrf_vb2_ops; - dev->vb_queue.mem_ops = &vb2_vmalloc_memops; - dev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - ret = vb2_queue_init(&dev->vb_queue); + /* Init vb2 queue structure for receiver */ + dev->rx_vb2_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE; + dev->rx_vb2_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | + VB2_READ; + dev->rx_vb2_queue.ops = &hackrf_vb2_ops; + dev->rx_vb2_queue.mem_ops = &vb2_vmalloc_memops; + dev->rx_vb2_queue.drv_priv = dev; + dev->rx_vb2_queue.buf_struct_size = sizeof(struct hackrf_buffer); + dev->rx_vb2_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + ret = vb2_queue_init(&dev->rx_vb2_queue); if (ret) { - dev_err(dev->dev, "Could not initialize vb2 queue\n"); - goto err_free_mem; + dev_err(dev->dev, "Could not initialize rx vb2 queue\n"); + goto err_kfree; } - /* Init video_device structure */ - dev->vdev = hackrf_template; - dev->vdev.queue = &dev->vb_queue; - dev->vdev.queue->lock = &dev->vb_queue_lock; - video_set_drvdata(&dev->vdev, dev); + /* Init vb2 queue structure for transmitter */ + dev->tx_vb2_queue.type = V4L2_BUF_TYPE_SDR_OUTPUT; + dev->tx_vb2_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | + VB2_WRITE; + dev->tx_vb2_queue.ops = &hackrf_vb2_ops; + dev->tx_vb2_queue.mem_ops = &vb2_vmalloc_memops; + dev->tx_vb2_queue.drv_priv = dev; + dev->tx_vb2_queue.buf_struct_size = sizeof(struct hackrf_buffer); + dev->tx_vb2_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + ret = vb2_queue_init(&dev->tx_vb2_queue); + if (ret) { + dev_err(dev->dev, "Could not initialize tx vb2 queue\n"); + goto err_kfree; + } + + /* Register controls for receiver */ + v4l2_ctrl_handler_init(&dev->rx_ctrl_handler, 5); + dev->rx_bandwidth_auto = v4l2_ctrl_new_std(&dev->rx_ctrl_handler, + &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, + 0, 1, 0, 1); + dev->rx_bandwidth = v4l2_ctrl_new_std(&dev->rx_ctrl_handler, + &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_BANDWIDTH, + 1750000, 28000000, 50000, 1750000); + v4l2_ctrl_auto_cluster(2, &dev->rx_bandwidth_auto, 0, false); + dev->rx_rf_gain = v4l2_ctrl_new_std(&dev->rx_ctrl_handler, + &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_RF_GAIN, 0, 12, 12, 0); + dev->rx_lna_gain = v4l2_ctrl_new_std(&dev->rx_ctrl_handler, + &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_LNA_GAIN, 0, 40, 8, 0); + dev->rx_if_gain = v4l2_ctrl_new_std(&dev->rx_ctrl_handler, + &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_IF_GAIN, 0, 62, 2, 0); + if (dev->rx_ctrl_handler.error) { + ret = dev->rx_ctrl_handler.error; + dev_err(dev->dev, "Could not initialize controls\n"); + goto err_v4l2_ctrl_handler_free_rx; + } + v4l2_ctrl_handler_setup(&dev->rx_ctrl_handler); + + /* Register controls for transmitter */ + v4l2_ctrl_handler_init(&dev->tx_ctrl_handler, 4); + dev->tx_bandwidth_auto = v4l2_ctrl_new_std(&dev->tx_ctrl_handler, + &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, + 0, 1, 0, 1); + dev->tx_bandwidth = v4l2_ctrl_new_std(&dev->tx_ctrl_handler, + &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_BANDWIDTH, + 1750000, 28000000, 50000, 1750000); + v4l2_ctrl_auto_cluster(2, &dev->tx_bandwidth_auto, 0, false); + dev->tx_lna_gain = v4l2_ctrl_new_std(&dev->tx_ctrl_handler, + &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_LNA_GAIN, 0, 47, 1, 0); + dev->tx_rf_gain = v4l2_ctrl_new_std(&dev->tx_ctrl_handler, + &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_RF_GAIN, 0, 15, 15, 0); + if (dev->tx_ctrl_handler.error) { + ret = dev->tx_ctrl_handler.error; + dev_err(dev->dev, "Could not initialize controls\n"); + goto err_v4l2_ctrl_handler_free_tx; + } + v4l2_ctrl_handler_setup(&dev->tx_ctrl_handler); /* Register the v4l2_device structure */ dev->v4l2_dev.release = hackrf_video_release; ret = v4l2_device_register(&intf->dev, &dev->v4l2_dev); if (ret) { dev_err(dev->dev, "Failed to register v4l2-device (%d)\n", ret); - goto err_free_mem; + goto err_v4l2_ctrl_handler_free_tx; } - /* Register controls */ - v4l2_ctrl_handler_init(&dev->hdl, 4); - dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops, - V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1); - dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops, - V4L2_CID_RF_TUNER_BANDWIDTH, - 1750000, 28000000, 50000, 1750000); - v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false); - dev->lna_gain = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops, - V4L2_CID_RF_TUNER_LNA_GAIN, 0, 40, 8, 0); - dev->if_gain = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops, - V4L2_CID_RF_TUNER_IF_GAIN, 0, 62, 2, 0); - if (dev->hdl.error) { - ret = dev->hdl.error; - dev_err(dev->dev, "Could not initialize controls\n"); - goto err_free_controls; + /* Init video_device structure for receiver */ + dev->rx_vdev = hackrf_template; + dev->rx_vdev.queue = &dev->rx_vb2_queue; + dev->rx_vdev.queue->lock = &dev->vb_queue_lock; + dev->rx_vdev.v4l2_dev = &dev->v4l2_dev; + dev->rx_vdev.ctrl_handler = &dev->rx_ctrl_handler; + dev->rx_vdev.lock = &dev->v4l2_lock; + dev->rx_vdev.vfl_dir = VFL_DIR_RX; + video_set_drvdata(&dev->rx_vdev, dev); + ret = video_register_device(&dev->rx_vdev, VFL_TYPE_SDR, -1); + if (ret) { + dev_err(dev->dev, + "Failed to register as video device (%d)\n", ret); + goto err_v4l2_device_unregister; } - - v4l2_ctrl_handler_setup(&dev->hdl); - - dev->v4l2_dev.ctrl_handler = &dev->hdl; - dev->vdev.v4l2_dev = &dev->v4l2_dev; - dev->vdev.lock = &dev->v4l2_lock; - - ret = video_register_device(&dev->vdev, VFL_TYPE_SDR, -1); + dev_info(dev->dev, "Registered as %s\n", + video_device_node_name(&dev->rx_vdev)); + + /* Init video_device structure for transmitter */ + dev->tx_vdev = hackrf_template; + dev->tx_vdev.queue = &dev->tx_vb2_queue; + dev->tx_vdev.queue->lock = &dev->vb_queue_lock; + dev->tx_vdev.v4l2_dev = &dev->v4l2_dev; + dev->tx_vdev.ctrl_handler = &dev->tx_ctrl_handler; + dev->tx_vdev.lock = &dev->v4l2_lock; + dev->tx_vdev.vfl_dir = VFL_DIR_TX; + video_set_drvdata(&dev->tx_vdev, dev); + ret = video_register_device(&dev->tx_vdev, VFL_TYPE_SDR, -1); if (ret) { - dev_err(dev->dev, "Failed to register as video device (%d)\n", - ret); - goto err_unregister_v4l2_dev; + dev_err(dev->dev, + "Failed to register as video device (%d)\n", ret); + goto err_video_unregister_device_rx; } dev_info(dev->dev, "Registered as %s\n", - video_device_node_name(&dev->vdev)); + video_device_node_name(&dev->tx_vdev)); + dev_notice(dev->dev, "SDR API is still slightly experimental and functionality changes may follow\n"); return 0; - -err_free_controls: - v4l2_ctrl_handler_free(&dev->hdl); -err_unregister_v4l2_dev: +err_video_unregister_device_rx: + video_unregister_device(&dev->rx_vdev); +err_v4l2_device_unregister: v4l2_device_unregister(&dev->v4l2_dev); -err_free_mem: +err_v4l2_ctrl_handler_free_tx: + v4l2_ctrl_handler_free(&dev->tx_ctrl_handler); +err_v4l2_ctrl_handler_free_rx: + v4l2_ctrl_handler_free(&dev->rx_ctrl_handler); +err_kfree: kfree(dev); +err: + dev_dbg(dev->dev, "failed=%d\n", ret); return ret; } diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index 3f276d921cca..e06a21a4fbd9 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -28,6 +28,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-event.h> #include <linux/usb.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> #include <linux/spi/spi.h> @@ -112,7 +113,8 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats); /* intermediate buffers with raw data from the USB device */ struct msi2500_frame_buf { - struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ + /* common v4l buffer stuff -- must be first */ + struct vb2_v4l2_buffer vb; struct list_head list; }; @@ -431,10 +433,10 @@ static void msi2500_isoc_handler(struct urb *urb) } /* fill framebuffer */ - ptr = vb2_plane_vaddr(&fbuf->vb, 0); + ptr = vb2_plane_vaddr(&fbuf->vb.vb2_buf, 0); flen = msi2500_convert_stream(dev, ptr, iso_buf, flen); - vb2_set_plane_payload(&fbuf->vb, 0, flen); - vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); + vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, flen); + vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); } handler_end: @@ -569,7 +571,7 @@ static void msi2500_cleanup_queued_bufs(struct msi2500_dev *dev) buf = list_entry(dev->queued_bufs.next, struct msi2500_frame_buf, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&dev->queued_bufs_lock, flags); } @@ -614,7 +616,7 @@ static int msi2500_querycap(struct file *file, void *fh, /* Videobuf2 operations */ static int msi2500_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, + const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) @@ -633,15 +635,16 @@ static int msi2500_queue_setup(struct vb2_queue *vq, static void msi2500_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct msi2500_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct msi2500_frame_buf *buf = container_of(vb, + struct msi2500_frame_buf *buf = container_of(vbuf, struct msi2500_frame_buf, vb); unsigned long flags; /* Check the device has not disconnected between prep and queuing */ if (unlikely(!dev->udev)) { - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); return; } diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index 702267e208ba..b79c36fd8cd2 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -240,9 +240,9 @@ static void pwc_frame_complete(struct pwc_device *pdev) PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);" " discarded.\n", fbuf->filled); } else { - fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE; - fbuf->vb.v4l2_buf.sequence = pdev->vframe_count; - vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); + fbuf->vb.field = V4L2_FIELD_NONE; + fbuf->vb.sequence = pdev->vframe_count; + vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); pdev->fill_buf = NULL; pdev->vsync = 0; } @@ -287,7 +287,7 @@ static void pwc_isoc_handler(struct urb *urb) { PWC_ERROR("Too many ISOC errors, bailing out.\n"); if (pdev->fill_buf) { - vb2_buffer_done(&pdev->fill_buf->vb, + vb2_buffer_done(&pdev->fill_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); pdev->fill_buf = NULL; } @@ -317,7 +317,7 @@ static void pwc_isoc_handler(struct urb *urb) if (pdev->vsync == 1) { v4l2_get_timestamp( - &fbuf->vb.v4l2_buf.timestamp); + &fbuf->vb.timestamp); pdev->vsync = 2; } @@ -520,7 +520,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev, buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, state); + vb2_buffer_done(&buf->vb.vb2_buf, state); } spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); } @@ -571,7 +571,7 @@ static void pwc_video_release(struct v4l2_device *v) /***************************************************************************/ /* Videobuf2 operations */ -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *vq, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -594,7 +594,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, static int buffer_init(struct vb2_buffer *vb) { - struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct pwc_frame_buf *buf = + container_of(vbuf, struct pwc_frame_buf, vb); /* need vmalloc since frame buffer > 128K */ buf->data = vzalloc(PWC_FRAME_SIZE); @@ -618,7 +620,9 @@ static int buffer_prepare(struct vb2_buffer *vb) static void buffer_finish(struct vb2_buffer *vb) { struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue); - struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct pwc_frame_buf *buf = + container_of(vbuf, struct pwc_frame_buf, vb); if (vb->state == VB2_BUF_STATE_DONE) { /* @@ -633,7 +637,9 @@ static void buffer_finish(struct vb2_buffer *vb) static void buffer_cleanup(struct vb2_buffer *vb) { - struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct pwc_frame_buf *buf = + container_of(vbuf, struct pwc_frame_buf, vb); vfree(buf->data); } @@ -641,12 +647,14 @@ static void buffer_cleanup(struct vb2_buffer *vb) static void buffer_queue(struct vb2_buffer *vb) { struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue); - struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct pwc_frame_buf *buf = + container_of(vbuf, struct pwc_frame_buf, vb); unsigned long flags = 0; /* Check the device has not disconnected between prep and queuing */ if (!pdev->udev) { - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); return; } @@ -695,7 +703,8 @@ static void stop_streaming(struct vb2_queue *vq) pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_ERROR); if (pdev->fill_buf) - vb2_buffer_done(&pdev->fill_buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&pdev->fill_buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); mutex_unlock(&pdev->v4l2_lock); } diff --git a/drivers/media/usb/pwc/pwc-uncompress.c b/drivers/media/usb/pwc/pwc-uncompress.c index b65903fbcf0d..98c46f93f119 100644 --- a/drivers/media/usb/pwc/pwc-uncompress.c +++ b/drivers/media/usb/pwc/pwc-uncompress.c @@ -40,7 +40,7 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) u16 *src; u16 *dsty, *dstu, *dstv; - image = vb2_plane_vaddr(&fbuf->vb, 0); + image = vb2_plane_vaddr(&fbuf->vb.vb2_buf, 0); yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ @@ -55,12 +55,12 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) * determine this using the type of the webcam */ memcpy(raw_frame->cmd, pdev->cmd_buf, 4); memcpy(raw_frame+1, yuv, pdev->frame_size); - vb2_set_plane_payload(&fbuf->vb, 0, + vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, pdev->frame_size + sizeof(struct pwc_raw_frame)); return 0; } - vb2_set_plane_payload(&fbuf->vb, 0, + vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, pdev->width * pdev->height * 3 / 2); if (pdev->vbandlength == 0) { diff --git a/drivers/media/usb/pwc/pwc.h b/drivers/media/usb/pwc/pwc.h index 81b017a554bc..3c73bdaae450 100644 --- a/drivers/media/usb/pwc/pwc.h +++ b/drivers/media/usb/pwc/pwc.h @@ -40,6 +40,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-fh.h> #include <media/v4l2-event.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> #ifdef CONFIG_USB_PWC_INPUT_EVDEV #include <linux/input.h> @@ -210,7 +211,8 @@ struct pwc_raw_frame { /* intermediate buffers with raw data from the USB cam */ struct pwc_frame_buf { - struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ + /* common v4l buffer stuff -- must be first */ + struct vb2_v4l2_buffer vb; struct list_head list; void *data; int filled; /* number of bytes filled */ diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index 0f3c34d47ec3..e7acb12ad21d 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -45,6 +45,7 @@ #include <linux/mm.h> #include <linux/vmalloc.h> #include <linux/usb.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> #include <media/v4l2-common.h> #include <media/v4l2-device.h> @@ -293,7 +294,7 @@ struct s2255_fmt { /* buffer for one video frame */ struct s2255_buffer { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; @@ -573,14 +574,14 @@ 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.v4l2_buf.timestamp); - buf->vb.v4l2_buf.field = vc->field; - buf->vb.v4l2_buf.sequence = vc->frame_count; + v4l2_get_timestamp(&buf->vb.timestamp); + buf->vb.field = vc->field; + buf->vb.sequence = vc->frame_count; spin_unlock_irqrestore(&vc->qlock, flags); s2255_fillbuff(vc, buf, jpgsize); /* tell v4l buffer was filled */ - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); dprintk(dev, 2, "%s: [buf] [%p]\n", __func__, buf); } @@ -612,7 +613,7 @@ static void s2255_fillbuff(struct s2255_vc *vc, { int pos = 0; const char *tmpbuf; - char *vbuf = vb2_plane_vaddr(&buf->vb, 0); + char *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); unsigned long last_frame; struct s2255_dev *dev = vc->dev; @@ -635,7 +636,7 @@ static void s2255_fillbuff(struct s2255_vc *vc, break; case V4L2_PIX_FMT_JPEG: case V4L2_PIX_FMT_MJPEG: - vb2_set_plane_payload(&buf->vb, 0, jpgsize); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, jpgsize); memcpy(vbuf, tmpbuf, jpgsize); break; case V4L2_PIX_FMT_YUV422P: @@ -659,7 +660,7 @@ static void s2255_fillbuff(struct s2255_vc *vc, Videobuf operations ------------------------------------------------------------------*/ -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int queue_setup(struct vb2_queue *vq, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -674,7 +675,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, static int buffer_prepare(struct vb2_buffer *vb) { struct s2255_vc *vc = vb2_get_drv_priv(vb->vb2_queue); - struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct s2255_buffer *buf = container_of(vbuf, struct s2255_buffer, vb); int w = vc->width; int h = vc->height; unsigned long size; @@ -696,13 +698,14 @@ static int buffer_prepare(struct vb2_buffer *vb) return -EINVAL; } - vb2_set_plane_payload(&buf->vb, 0, size); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); return 0; } static void buffer_queue(struct vb2_buffer *vb) { - struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct s2255_buffer *buf = container_of(vbuf, struct s2255_buffer, vb); struct s2255_vc *vc = vb2_get_drv_priv(vb->vb2_queue); unsigned long flags = 0; dprintk(vc->dev, 1, "%s\n", __func__); @@ -1116,9 +1119,9 @@ static void stop_streaming(struct vb2_queue *vq) spin_lock_irqsave(&vc->qlock, flags); list_for_each_entry_safe(buf, node, &vc->buf_list, list) { list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); dprintk(vc->dev, 2, "[%p/%d] done\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } spin_unlock_irqrestore(&vc->qlock, flags); } diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index e12b10352871..0bd34f1e7fa9 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -664,7 +664,7 @@ static const struct v4l2_ioctl_ops stk1160_ioctl_ops = { /* * Videobuf2 operations */ -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt, +static int queue_setup(struct vb2_queue *vq, const void *parg, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -695,8 +695,9 @@ static void buffer_queue(struct vb2_buffer *vb) { unsigned long flags; struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct stk1160_buffer *buf = - container_of(vb, struct stk1160_buffer, vb); + container_of(vbuf, struct stk1160_buffer, vb); spin_lock_irqsave(&dev->buf_lock, flags); if (!dev->udev) { @@ -704,7 +705,7 @@ static void buffer_queue(struct vb2_buffer *vb) * If the device is disconnected return the buffer to userspace * directly. The next QBUF call will fail with -ENODEV. */ - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } else { buf->mem = vb2_plane_vaddr(vb, 0); @@ -717,7 +718,7 @@ static void buffer_queue(struct vb2_buffer *vb) * the buffer to userspace directly. */ if (buf->length < dev->width * dev->height * 2) - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); else list_add_tail(&buf->list, &dev->avail_bufs); @@ -769,9 +770,9 @@ void stk1160_clear_queue(struct stk1160 *dev) buf = list_first_entry(&dev->avail_bufs, struct stk1160_buffer, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); stk1160_dbg("buffer [%p/%d] aborted\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } /* It's important to release the current buffer */ @@ -779,9 +780,9 @@ void stk1160_clear_queue(struct stk1160 *dev) buf = dev->isoc_ctl.buf; dev->isoc_ctl.buf = NULL; - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); stk1160_dbg("buffer [%p/%d] aborted\n", - buf, buf->vb.v4l2_buf.index); + buf, buf->vb.vb2_buf.index); } spin_unlock_irqrestore(&dev->buf_lock, flags); } diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index 940c3eaea507..75654e676e80 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -96,13 +96,13 @@ void stk1160_buffer_done(struct stk1160 *dev) { struct stk1160_buffer *buf = dev->isoc_ctl.buf; - buf->vb.v4l2_buf.sequence = dev->sequence++; - buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; - buf->vb.v4l2_buf.bytesused = buf->bytesused; - v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + 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); - vb2_set_plane_payload(&buf->vb, 0, buf->bytesused); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->bytesused); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); dev->isoc_ctl.buf = NULL; } diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h index 72cc8e8cbef7..1ed1cc43cdb2 100644 --- a/drivers/media/usb/stk1160/stk1160.h +++ b/drivers/media/usb/stk1160/stk1160.h @@ -23,7 +23,7 @@ #include <linux/i2c.h> #include <sound/core.h> #include <sound/ac97_codec.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> @@ -77,7 +77,7 @@ /* Buffer for one video frame */ struct stk1160_buffer { /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; void *mem; diff --git a/drivers/media/usb/tm6000/tm6000-alsa.c b/drivers/media/usb/tm6000/tm6000-alsa.c index 74e5697d8678..e21c7aacecb6 100644 --- a/drivers/media/usb/tm6000/tm6000-alsa.c +++ b/drivers/media/usb/tm6000/tm6000-alsa.c @@ -42,7 +42,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; +static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled."); diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c index 7c3a7c55d969..a5de46f04247 100644 --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c @@ -375,8 +375,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data) struct ttusb_dec *dec = priv; dec->audio_filter->feed->cb.ts(data, 188, NULL, 0, - &dec->audio_filter->feed->feed.ts, - DMX_OK); + &dec->audio_filter->feed->feed.ts); return 0; } @@ -386,8 +385,7 @@ static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data) struct ttusb_dec *dec = priv; dec->video_filter->feed->cb.ts(data, 188, NULL, 0, - &dec->video_filter->feed->feed.ts, - DMX_OK); + &dec->video_filter->feed->feed.ts); return 0; } @@ -439,7 +437,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length) if (output_pva) { dec->video_filter->feed->cb.ts(pva, length, NULL, 0, - &dec->video_filter->feed->feed.ts, DMX_OK); + &dec->video_filter->feed->feed.ts); return; } @@ -500,7 +498,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length) case 0x02: /* MainAudioStream */ if (output_pva) { dec->audio_filter->feed->cb.ts(pva, length, NULL, 0, - &dec->audio_filter->feed->feed.ts, DMX_OK); + &dec->audio_filter->feed->feed.ts); return; } @@ -538,7 +536,7 @@ static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet, if (filter) filter->feed->cb.sec(&packet[2], length - 2, NULL, 0, - &filter->filter, DMX_OK); + &filter->filter); } static void ttusb_dec_process_packet(struct ttusb_dec *dec) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 08fb0f2da64d..e645c9df2d94 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -29,7 +29,7 @@ */ #include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include "usbtv.h" @@ -306,7 +306,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk) /* First available buffer. */ buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list); - frame = vb2_plane_vaddr(&buf->vb, 0); + frame = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); /* Copy the chunk data. */ usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); @@ -314,17 +314,17 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk) /* Last chunk in a frame, signalling an end */ if (odd && chunk_no == usbtv->n_chunks-1) { - int size = vb2_plane_size(&buf->vb, 0); + int size = vb2_plane_size(&buf->vb.vb2_buf, 0); enum vb2_buffer_state state = usbtv->chunks_done == usbtv->n_chunks ? VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; - buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; - buf->vb.v4l2_buf.sequence = usbtv->sequence++; - v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); - vb2_set_plane_payload(&buf->vb, 0, size); - vb2_buffer_done(&buf->vb, state); + buf->vb.field = V4L2_FIELD_INTERLACED; + buf->vb.sequence = usbtv->sequence++; + v4l2_get_timestamp(&buf->vb.timestamp); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); + vb2_buffer_done(&buf->vb.vb2_buf, state); list_del(&buf->list); } @@ -422,7 +422,7 @@ static void usbtv_stop(struct usbtv *usbtv) while (!list_empty(&usbtv->bufs)) { struct usbtv_buf *buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); list_del(&buf->list); } spin_unlock_irqrestore(&usbtv->buflock, flags); @@ -599,9 +599,10 @@ static struct v4l2_file_operations usbtv_fops = { }; static int usbtv_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, unsigned int *nbuffers, + const void *parg, 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); @@ -617,8 +618,9 @@ static int usbtv_queue_setup(struct vb2_queue *vq, static void usbtv_buf_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct usbtv *usbtv = vb2_get_drv_priv(vb->vb2_queue); - struct usbtv_buf *buf = container_of(vb, struct usbtv_buf, vb); + struct usbtv_buf *buf = container_of(vbuf, struct usbtv_buf, vb); unsigned long flags; if (usbtv->udev == NULL) { diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h index 968119581fab..19cb8bf7c4e9 100644 --- a/drivers/media/usb/usbtv/usbtv.h +++ b/drivers/media/usb/usbtv/usbtv.h @@ -24,6 +24,7 @@ #include <linux/usb.h> #include <media/v4l2-device.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> /* Hardware. */ @@ -61,7 +62,7 @@ struct usbtv_norm_params { /* A single videobuf2 frame buffer. */ struct usbtv_buf { - struct vb2_buffer vb; + struct vb2_v4l2_buffer vb; struct list_head list; }; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 4b5b3e8fb7d3..d11fd6ac2df0 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -32,6 +32,7 @@ #define DRIVER_DESC "USB Video Class driver" unsigned int uvc_clock_param = CLOCK_MONOTONIC; +unsigned int uvc_hw_timestamps_param; unsigned int uvc_no_drop_param; static unsigned int uvc_quirks_param = -1; unsigned int uvc_trace_param; @@ -2078,6 +2079,8 @@ static int uvc_clock_param_set(const char *val, struct kernel_param *kp) module_param_call(clock, uvc_clock_param_set, uvc_clock_param_get, &uvc_clock_param, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(clock, "Video buffers timestamp clock"); +module_param_named(hwtimestamps, uvc_hw_timestamps_param, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(hwtimestamps, "Use hardware timestamps"); module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames"); module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index f16b9b42689d..cfb868a48b5f 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -20,6 +20,7 @@ #include <linux/videodev2.h> #include <linux/vmalloc.h> #include <linux/wait.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> #include "uvcvideo.h" @@ -60,7 +61,7 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue, queue); list_del(&buf->queue); buf->state = state; - vb2_buffer_done(&buf->buf, vb2_state); + vb2_buffer_done(&buf->buf.vb2_buf, vb2_state); } } @@ -68,10 +69,11 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue, * videobuf2 queue operations */ -static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int uvc_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 uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); @@ -89,10 +91,11 @@ static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, static int uvc_buffer_prepare(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); - struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); + struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf); - if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT && + if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n"); return -EINVAL; @@ -105,7 +108,7 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb) buf->error = 0; buf->mem = vb2_plane_vaddr(vb, 0); buf->length = vb2_plane_size(vb, 0); - if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) buf->bytesused = 0; else buf->bytesused = vb2_get_plane_payload(vb, 0); @@ -115,8 +118,9 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb) static void uvc_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); - struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); + struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf); unsigned long flags; spin_lock_irqsave(&queue->irqlock, flags); @@ -127,7 +131,7 @@ static void uvc_buffer_queue(struct vb2_buffer *vb) * directly. The next QBUF call will fail with -ENODEV. */ buf->state = UVC_BUF_STATE_ERROR; - vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&queue->irqlock, flags); @@ -135,12 +139,13 @@ static void uvc_buffer_queue(struct vb2_buffer *vb) static void uvc_buffer_finish(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); struct uvc_streaming *stream = uvc_queue_to_stream(queue); - struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); + struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf); if (vb->state == VB2_BUF_STATE_DONE) - uvc_video_clock_update(stream, &vb->v4l2_buf, buf); + uvc_video_clock_update(stream, vbuf, buf); } static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count) @@ -398,7 +403,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, buf->error = 0; buf->state = UVC_BUF_STATE_QUEUED; buf->bytesused = 0; - vb2_set_plane_payload(&buf->buf, 0, 0); + vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0); return buf; } @@ -412,8 +417,8 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, spin_unlock_irqrestore(&queue->irqlock, flags); buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE; - vb2_set_plane_payload(&buf->buf, 0, buf->bytesused); - vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE); + vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused); + vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE); return nextbuf; } diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index f839654ea436..2b276ab7764f 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -606,7 +606,7 @@ static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample) * timestamp of the sliding window to 1s. */ void uvc_video_clock_update(struct uvc_streaming *stream, - struct v4l2_buffer *v4l2_buf, + struct vb2_v4l2_buffer *vbuf, struct uvc_buffer *buf) { struct uvc_clock *clock = &stream->clock; @@ -623,6 +623,9 @@ void uvc_video_clock_update(struct uvc_streaming *stream, u32 rem; u64 y; + if (!uvc_hw_timestamps_param) + return; + spin_lock_irqsave(&clock->lock, flags); if (clock->count < clock->size) @@ -696,14 +699,14 @@ void uvc_video_clock_update(struct uvc_streaming *stream, stream->dev->name, sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536), y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC, - v4l2_buf->timestamp.tv_sec, - (unsigned long)v4l2_buf->timestamp.tv_usec, + vbuf->timestamp.tv_sec, + (unsigned long)vbuf->timestamp.tv_usec, x1, first->host_sof, first->dev_sof, x2, last->host_sof, last->dev_sof, y1, y2); /* Update the V4L2 buffer. */ - v4l2_buf->timestamp.tv_sec = ts.tv_sec; - v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; + vbuf->timestamp.tv_sec = ts.tv_sec; + vbuf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; done: spin_unlock_irqrestore(&stream->clock.lock, flags); @@ -1029,10 +1032,10 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, uvc_video_get_ts(&ts); - buf->buf.v4l2_buf.field = V4L2_FIELD_NONE; - buf->buf.v4l2_buf.sequence = stream->sequence; - buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec; - buf->buf.v4l2_buf.timestamp.tv_usec = + 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; /* TODO: Handle PTS and SCR. */ @@ -1305,7 +1308,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, if (buf->bytesused == stream->queue.buf_used) { stream->queue.buf_used = 0; buf->state = UVC_BUF_STATE_READY; - buf->buf.v4l2_buf.sequence = ++stream->sequence; + buf->buf.sequence = ++stream->sequence; uvc_queue_next_buffer(&stream->queue, buf); stream->last_fid ^= UVC_STREAM_FID; } diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 816dd1a0fd81..f0f2391e1b43 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -15,7 +15,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-event.h> #include <media/v4l2-fh.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> /* -------------------------------------------------------------------------- * UVC constants @@ -354,7 +354,7 @@ enum uvc_buffer_state { }; struct uvc_buffer { - struct vb2_buffer buf; + struct vb2_v4l2_buffer buf; struct list_head queue; enum uvc_buffer_state state; @@ -593,6 +593,7 @@ extern unsigned int uvc_clock_param; extern unsigned int uvc_no_drop_param; extern unsigned int uvc_trace_param; extern unsigned int uvc_timeout_param; +extern unsigned int uvc_hw_timestamps_param; #define uvc_trace(flag, msg...) \ do { \ @@ -673,7 +674,7 @@ extern int uvc_probe_video(struct uvc_streaming *stream, extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, __u8 intfnum, __u8 cs, void *data, __u16 size); void uvc_video_clock_update(struct uvc_streaming *stream, - struct v4l2_buffer *v4l2_buf, + struct vb2_v4l2_buffer *vbuf, struct uvc_buffer *buf); /* Status */ diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index 82876a67f144..9beece00869b 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -47,7 +47,7 @@ config V4L2_MEM2MEM_DEV # Used by LED subsystem flash drivers config V4L2_FLASH_LED_CLASS tristate "V4L2 flash API for LED flash class devices" - depends on VIDEO_V4L2_SUBDEV_API + depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on LEDS_CLASS_FLASH ---help--- Say Y here to enable V4L2 flash API support for LED flash diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index d1dd440d9d9b..1dc8bba2b198 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -14,7 +14,7 @@ ifeq ($(CONFIG_OF),y) videodev-objs += v4l2-of.o endif ifeq ($(CONFIG_TRACEPOINTS),y) - videodev-objs += v4l2-trace.o + videodev-objs += vb2-trace.o v4l2-trace.o endif obj-$(CONFIG_VIDEO_V4L2) += videodev.o @@ -33,7 +33,7 @@ obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o -obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o +obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o videobuf2-v4l2.o obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index af635430524e..327e83ac2469 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -147,6 +147,20 @@ static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, return 0; } +static inline int get_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up) +{ + if (copy_from_user(kp, up, sizeof(struct v4l2_sdr_format))) + return -EFAULT; + return 0; +} + +static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up) +{ + if (copy_to_user(up, kp, sizeof(struct v4l2_sdr_format))) + return -EFAULT; + return 0; +} + struct v4l2_format32 { __u32 type; /* enum v4l2_buf_type */ union { @@ -155,6 +169,7 @@ struct v4l2_format32 { struct v4l2_window32 win; struct v4l2_vbi_format vbi; struct v4l2_sliced_vbi_format sliced; + struct v4l2_sdr_format sdr; __u8 raw_data[200]; /* user-defined */ } fmt; }; @@ -198,8 +213,11 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); + case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: + return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr); default: - printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", + pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n", kp->type); return -EINVAL; } @@ -242,8 +260,11 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); + case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: + return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr); default: - printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", + pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n", kp->type); return -EINVAL; } @@ -266,7 +287,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_ struct v4l2_standard32 { __u32 index; - __u32 id[2]; /* __u64 would get the alignment wrong */ + compat_u64 id; __u8 name[24]; struct v4l2_fract frameperiod; /* Frames, not fields */ __u32 framelines; @@ -286,7 +307,7 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 { if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || put_user(kp->index, &up->index) || - copy_to_user(up->id, &kp->id, sizeof(__u64)) || + put_user(kp->id, &up->id) || copy_to_user(up->name, kp->name, 24) || copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || put_user(kp->framelines, &up->framelines) || @@ -587,10 +608,10 @@ struct v4l2_input32 { __u32 type; /* Type of input */ __u32 audioset; /* Associated audios (bitfield) */ __u32 tuner; /* Associated tuner */ - v4l2_std_id std; + compat_u64 std; __u32 status; __u32 reserved[4]; -} __attribute__ ((packed)); +}; /* The 64-bit v4l2_input struct has extra padding at the end of the struct. Otherwise it is identical to the 32-bit version. */ @@ -609,11 +630,11 @@ static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __ } struct v4l2_ext_controls32 { - __u32 ctrl_class; - __u32 count; - __u32 error_idx; - __u32 reserved[2]; - compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ + __u32 ctrl_class; + __u32 count; + __u32 error_idx; + __u32 reserved[2]; + compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ }; struct v4l2_ext_control32 { @@ -655,7 +676,8 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext get_user(kp->ctrl_class, &up->ctrl_class) || get_user(kp->count, &up->count) || get_user(kp->error_idx, &up->error_idx) || - copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) + copy_from_user(kp->reserved, up->reserved, + sizeof(kp->reserved))) return -EFAULT; n = kp->count; if (n == 0) { @@ -738,6 +760,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext struct v4l2_event32 { __u32 type; union { + compat_s64 value64; __u8 data[64]; } u; __u32 pending; @@ -1033,8 +1056,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) ret = vdev->fops->compat_ioctl32(file, cmd, arg); if (ret == -ENOIOCTLCMD) - pr_warn("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", - _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); + pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", + _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); return ret; } EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index b6b7dcc1b77d..4a1d9fdd14bb 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -888,6 +888,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis"; case V4L2_CID_RDS_RECEPTION: return "RDS Reception"; case V4L2_CID_RF_TUNER_CLASS: return "RF Tuner Controls"; + case V4L2_CID_RF_TUNER_RF_GAIN: return "RF Gain"; case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO: return "LNA Gain, Auto"; case V4L2_CID_RF_TUNER_LNA_GAIN: return "LNA Gain"; case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO: return "Mixer Gain, Auto"; @@ -1161,6 +1162,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_PILOT_TONE_FREQUENCY: case V4L2_CID_TUNE_POWER_LEVEL: case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + case V4L2_CID_RF_TUNER_RF_GAIN: case V4L2_CID_RF_TUNER_LNA_GAIN: case V4L2_CID_RF_TUNER_MIXER_GAIN: case V4L2_CID_RF_TUNER_IF_GAIN: @@ -2498,7 +2500,7 @@ int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctr /* We found a control with the given ID, so just get the next valid one in the list. */ list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) { - is_compound = + is_compound = ref->ctrl->is_array || ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES; if (id < ref->ctrl->id && (is_compound & mask) == match) @@ -2512,7 +2514,7 @@ int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctr is one, otherwise the first 'if' above would have been true. */ list_for_each_entry(ref, &hdl->ctrl_refs, node) { - is_compound = + is_compound = ref->ctrl->is_array || ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES; if (id < ref->ctrl->id && (is_compound & mask) == match) @@ -2884,7 +2886,7 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) * cur_to_user() calls below would need to be modified not to access * userspace memory when called from get_ctrl(). */ - if (!ctrl->is_int) + if (!ctrl->is_int && ctrl->type != V4L2_CTRL_TYPE_INTEGER64) return -EINVAL; if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) @@ -2942,9 +2944,9 @@ s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl) /* It's a driver bug if this happens. */ WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64); - c.value = 0; + c.value64 = 0; get_ctrl(ctrl, &c); - return c.value; + return c.value64; } EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64); @@ -3043,7 +3045,7 @@ static void update_from_auto_cluster(struct v4l2_ctrl *master) { int i; - for (i = 0; i < master->ncontrols; i++) + for (i = 1; i < master->ncontrols; i++) cur_to_new(master->cluster[i]); if (!call_op(master, g_volatile_ctrl)) for (i = 1; i < master->ncontrols; i++) diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 71a1b93b0790..6b1eaeddbdb3 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -637,8 +637,8 @@ static void determine_valid_ioctls(struct video_device *vdev) ops->vidioc_try_fmt_sliced_vbi_out))) set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap); - } else if (is_sdr) { - /* SDR specific ioctls */ + } else if (is_sdr && is_rx) { + /* SDR receiver specific ioctls */ if (ops->vidioc_enum_fmt_sdr_cap) set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls); if (ops->vidioc_g_fmt_sdr_cap) @@ -647,6 +647,16 @@ static void determine_valid_ioctls(struct video_device *vdev) set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls); if (ops->vidioc_try_fmt_sdr_cap) set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); + } else if (is_sdr && is_tx) { + /* SDR transmitter specific ioctls */ + if (ops->vidioc_enum_fmt_sdr_out) + set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls); + if (ops->vidioc_g_fmt_sdr_out) + set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls); + if (ops->vidioc_s_fmt_sdr_out) + set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls); + if (ops->vidioc_try_fmt_sdr_out) + set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); } if (is_vid || is_vbi || is_sdr) { diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 4a384fc765b8..7486af2c8ae4 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -26,7 +26,7 @@ #include <media/v4l2-fh.h> #include <media/v4l2-event.h> #include <media/v4l2-device.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <trace/events/v4l2.h> @@ -153,6 +153,7 @@ const char *v4l2_type_names[] = { [V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane", [V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane", [V4L2_BUF_TYPE_SDR_CAPTURE] = "sdr-cap", + [V4L2_BUF_TYPE_SDR_OUTPUT] = "sdr-out", }; EXPORT_SYMBOL(v4l2_type_names); @@ -326,6 +327,7 @@ static void v4l_print_format(const void *arg, bool write_only) sliced->service_lines[1][i]); break; case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: sdr = &p->fmt.sdr; pr_cont(", pixelformat=%c%c%c%c\n", (sdr->pixelformat >> 0) & 0xff, @@ -974,6 +976,10 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type) if (is_sdr && is_rx && ops->vidioc_g_fmt_sdr_cap) return 0; break; + case V4L2_BUF_TYPE_SDR_OUTPUT: + if (is_sdr && is_tx && ops->vidioc_g_fmt_sdr_out) + return 0; + break; default: break; } @@ -1324,6 +1330,11 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, break; ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, arg); break; + case V4L2_BUF_TYPE_SDR_OUTPUT: + if (unlikely(!is_tx || !is_sdr || !ops->vidioc_enum_fmt_sdr_out)) + break; + ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg); + break; } if (ret == 0) v4l_fill_fmtdesc(p); @@ -1418,6 +1429,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!is_rx || !is_sdr || !ops->vidioc_g_fmt_sdr_cap)) break; return ops->vidioc_g_fmt_sdr_cap(file, fh, arg); + case V4L2_BUF_TYPE_SDR_OUTPUT: + if (unlikely(!is_tx || !is_sdr || !ops->vidioc_g_fmt_sdr_out)) + break; + return ops->vidioc_g_fmt_sdr_out(file, fh, arg); } return -EINVAL; } @@ -1497,6 +1512,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, break; CLEAR_AFTER_FIELD(p, fmt.sdr); return ops->vidioc_s_fmt_sdr_cap(file, fh, arg); + case V4L2_BUF_TYPE_SDR_OUTPUT: + if (unlikely(!is_tx || !is_sdr || !ops->vidioc_s_fmt_sdr_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.sdr); + return ops->vidioc_s_fmt_sdr_out(file, fh, arg); } return -EINVAL; } @@ -1576,6 +1596,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, break; CLEAR_AFTER_FIELD(p, fmt.sdr); return ops->vidioc_try_fmt_sdr_cap(file, fh, arg); + case V4L2_BUF_TYPE_SDR_OUTPUT: + if (unlikely(!is_tx || !is_sdr || !ops->vidioc_try_fmt_sdr_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.sdr); + return ops->vidioc_try_fmt_sdr_out(file, fh, arg); } return -EINVAL; } @@ -1621,15 +1646,31 @@ static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops, static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { + struct video_device *vfd = video_devdata(file); struct v4l2_modulator *p = arg; int err; + if (vfd->vfl_type == VFL_TYPE_RADIO) + p->type = V4L2_TUNER_RADIO; + err = ops->vidioc_g_modulator(file, fh, p); if (!err) p->capability |= V4L2_TUNER_CAP_FREQ_BANDS; return err; } +static int v4l_s_modulator(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_modulator *p = arg; + + if (vfd->vfl_type == VFL_TYPE_RADIO) + p->type = V4L2_TUNER_RADIO; + + return ops->vidioc_s_modulator(file, fh, p); +} + static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -1637,7 +1678,7 @@ static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops, struct v4l2_frequency *p = arg; if (vfd->vfl_type == VFL_TYPE_SDR) - p->type = V4L2_TUNER_ADC; + p->type = V4L2_TUNER_SDR; else p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; @@ -1652,7 +1693,7 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops, enum v4l2_tuner_type type; if (vfd->vfl_type == VFL_TYPE_SDR) { - if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF) + if (p->type != V4L2_TUNER_SDR && p->type != V4L2_TUNER_RF) return -EINVAL; } else { type = (vfd->vfl_type == VFL_TYPE_RADIO) ? @@ -2277,7 +2318,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, int err; if (vfd->vfl_type == VFL_TYPE_SDR) { - if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF) + if (p->type != V4L2_TUNER_SDR && p->type != V4L2_TUNER_RF) return -EINVAL; type = p->type; } else { @@ -2416,7 +2457,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0), IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_G_MODULATOR, v4l_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)), - IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_S_MODULATOR, v4l_s_modulator, v4l_print_modulator, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)), IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)), diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index ec3ad4eb0c57..61d56c940f80 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -17,7 +17,7 @@ #include <linux/sched.h> #include <linux/slab.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/v4l2-mem2mem.h> #include <media/v4l2-dev.h> #include <media/v4l2-fh.h> @@ -583,32 +583,25 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, goto end; } - if (m2m_ctx->m2m_dev->m2m_ops->unlock) - m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv); - else if (m2m_ctx->q_lock) - mutex_unlock(m2m_ctx->q_lock); - + spin_lock_irqsave(&src_q->done_lock, flags); if (list_empty(&src_q->done_list)) poll_wait(file, &src_q->done_wq, wait); + spin_unlock_irqrestore(&src_q->done_lock, flags); + + spin_lock_irqsave(&dst_q->done_lock, flags); if (list_empty(&dst_q->done_list)) { /* * If the last buffer was dequeued from the capture queue, * return immediately. DQBUF will return -EPIPE. */ - if (dst_q->last_buffer_dequeued) + if (dst_q->last_buffer_dequeued) { + spin_unlock_irqrestore(&dst_q->done_lock, flags); return rc | POLLIN | POLLRDNORM; + } poll_wait(file, &dst_q->done_wq, wait); } - - if (m2m_ctx->m2m_dev->m2m_ops->lock) - m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv); - else if (m2m_ctx->q_lock) { - if (mutex_lock_interruptible(m2m_ctx->q_lock)) { - rc |= POLLERR; - goto end; - } - } + spin_unlock_irqrestore(&dst_q->done_lock, flags); spin_lock_irqsave(&src_q->done_lock, flags); if (!list_empty(&src_q->done_list)) @@ -773,13 +766,15 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_release); * * Call from buf_queue(), videobuf_queue_ops callback. */ -void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb) +void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, + struct vb2_v4l2_buffer *vbuf) { - struct v4l2_m2m_buffer *b = container_of(vb, struct v4l2_m2m_buffer, vb); + struct v4l2_m2m_buffer *b = container_of(vbuf, + struct v4l2_m2m_buffer, vb); struct v4l2_m2m_queue_ctx *q_ctx; unsigned long flags; - q_ctx = get_queue_ctx(m2m_ctx, vb->vb2_queue->type); + q_ctx = get_queue_ctx(m2m_ctx, vbuf->vb2_buf.vb2_queue->type); if (!q_ctx) return; diff --git a/drivers/media/v4l2-core/v4l2-trace.c b/drivers/media/v4l2-core/v4l2-trace.c index ae10b0248c8e..7416010542c1 100644 --- a/drivers/media/v4l2-core/v4l2-trace.c +++ b/drivers/media/v4l2-core/v4l2-trace.c @@ -1,11 +1,11 @@ #include <media/v4l2-common.h> #include <media/v4l2-fh.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #define CREATE_TRACE_POINTS #include <trace/events/v4l2.h> -EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_done); -EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_queue); -EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_dqbuf); -EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_qbuf); +EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_done); +EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_queue); +EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_dqbuf); +EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_qbuf); diff --git a/drivers/media/v4l2-core/vb2-trace.c b/drivers/media/v4l2-core/vb2-trace.c new file mode 100644 index 000000000000..61e74f5936b3 --- /dev/null +++ b/drivers/media/v4l2-core/vb2-trace.c @@ -0,0 +1,9 @@ +#include <media/videobuf2-core.h> + +#define CREATE_TRACE_POINTS +#include <trace/events/vb2.h> + +EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_done); +EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_queue); +EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_dqbuf); +EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_qbuf); diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c index 926836d1813a..6c02989ee33f 100644 --- a/drivers/media/v4l2-core/videobuf-core.c +++ b/drivers/media/v4l2-core/videobuf-core.c @@ -576,7 +576,8 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) } if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT || q->type == V4L2_BUF_TYPE_VBI_OUTPUT - || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { + || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT + || q->type == V4L2_BUF_TYPE_SDR_OUTPUT) { buf->size = b->bytesused; buf->field = b->field; buf->ts = b->timestamp; @@ -1154,6 +1155,7 @@ unsigned int videobuf_poll_stream(struct file *file, case V4L2_BUF_TYPE_VIDEO_OUTPUT: case V4L2_BUF_TYPE_VBI_OUTPUT: case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + case V4L2_BUF_TYPE_SDR_OUTPUT: rc = POLLOUT | POLLWRNORM; break; default: diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 4f59b7ec05d0..33bdd81065e8 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1,5 +1,5 @@ /* - * videobuf2-core.c - V4L2 driver helper framework + * videobuf2-core.c - video buffer 2 core framework * * Copyright (C) 2010 Samsung Electronics * @@ -24,164 +24,15 @@ #include <linux/freezer.h> #include <linux/kthread.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-event.h> -#include <media/v4l2-common.h> #include <media/videobuf2-core.h> -#include <trace/events/v4l2.h> +#include <trace/events/vb2.h> -static int debug; -module_param(debug, int, 0644); +#include "videobuf2-internal.h" -#define dprintk(level, fmt, arg...) \ - do { \ - if (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)->v4l2_buf.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)->v4l2_buf.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 - -/* Flags that are set by the vb2 core */ -#define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \ - V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \ - V4L2_BUF_FLAG_PREPARED | \ - V4L2_BUF_FLAG_TIMESTAMP_MASK) -/* Output buffer flags that should be passed on to the driver */ -#define V4L2_BUFFER_OUT_FLAGS (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \ - V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE) +int vb2_debug; +EXPORT_SYMBOL_GPL(vb2_debug); +module_param_named(debug, vb2_debug, int, 0644); static void __vb2_queue_cancel(struct vb2_queue *q); static void __enqueue_in_driver(struct vb2_buffer *vb); @@ -193,7 +44,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; enum dma_data_direction dma_dir = - V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; void *mem_priv; int plane; @@ -211,7 +62,7 @@ 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->v4l2_planes[plane].length = q->plane_sizes[plane]; + vb->planes[plane].length = q->plane_sizes[plane]; } return 0; @@ -235,8 +86,7 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb) for (plane = 0; plane < vb->num_planes; ++plane) { call_void_memop(vb, put, vb->planes[plane].mem_priv); vb->planes[plane].mem_priv = NULL; - dprintk(3, "freed plane %d of buffer %d\n", plane, - vb->v4l2_buf.index); + dprintk(3, "freed plane %d of buffer %d\n", plane, vb->index); } } @@ -269,7 +119,9 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p) call_void_memop(vb, detach_dmabuf, p->mem_priv); dma_buf_put(p->dbuf); - memset(p, 0, sizeof(*p)); + p->mem_priv = NULL; + p->dbuf = NULL; + p->dbuf_mapped = 0; } /** @@ -299,7 +151,7 @@ static void __setup_lengths(struct vb2_queue *q, unsigned int n) continue; for (plane = 0; plane < vb->num_planes; ++plane) - vb->v4l2_planes[plane].length = q->plane_sizes[plane]; + vb->planes[plane].length = q->plane_sizes[plane]; } } @@ -314,10 +166,10 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n) unsigned long off; if (q->num_buffers) { - struct v4l2_plane *p; + struct vb2_plane *p; vb = q->bufs[q->num_buffers - 1]; - p = &vb->v4l2_planes[vb->num_planes - 1]; - off = PAGE_ALIGN(p->m.mem_offset + p->length); + p = &vb->planes[vb->num_planes - 1]; + off = PAGE_ALIGN(p->m.offset + p->length); } else { off = 0; } @@ -328,12 +180,12 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n) continue; for (plane = 0; plane < vb->num_planes; ++plane) { - vb->v4l2_planes[plane].m.mem_offset = off; + vb->planes[plane].m.offset = off; dprintk(3, "buffer %d, plane %d offset 0x%08lx\n", buffer, plane, off); - off += vb->v4l2_planes[plane].length; + off += vb->planes[plane].length; off = PAGE_ALIGN(off); } } @@ -346,7 +198,7 @@ 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 v4l2_memory memory, +static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory, unsigned int num_buffers, unsigned int num_planes) { unsigned int buffer; @@ -361,19 +213,15 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, break; } - /* Length stores number of planes for multiplanar buffers */ - if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) - vb->v4l2_buf.length = num_planes; - vb->state = VB2_BUF_STATE_DEQUEUED; vb->vb2_queue = q; vb->num_planes = num_planes; - vb->v4l2_buf.index = q->num_buffers + buffer; - vb->v4l2_buf.type = q->type; - vb->v4l2_buf.memory = memory; + vb->index = q->num_buffers + buffer; + vb->type = q->type; + vb->memory = memory; /* Allocate video buffer memory for the MMAP type */ - if (memory == V4L2_MEMORY_MMAP) { + if (memory == VB2_MEMORY_MMAP) { ret = __vb2_buf_mem_alloc(vb); if (ret) { dprintk(1, "failed allocating memory for " @@ -400,7 +248,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, } __setup_lengths(q, buffer); - if (memory == V4L2_MEMORY_MMAP) + if (memory == VB2_MEMORY_MMAP) __setup_offsets(q, buffer); dprintk(1, "allocated %d buffers, %d plane(s) each\n", @@ -424,9 +272,9 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers) continue; /* Free MMAP buffers or release USERPTR buffers */ - if (q->memory == V4L2_MEMORY_MMAP) + if (q->memory == VB2_MEMORY_MMAP) __vb2_buf_mem_free(vb); - else if (q->memory == V4L2_MEMORY_DMABUF) + else if (q->memory == VB2_MEMORY_DMABUF) __vb2_buf_dmabuf_put(vb); else __vb2_buf_userptr_put(vb); @@ -482,7 +330,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 || debug) { + if (unbalanced || vb2_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", @@ -508,7 +356,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 || debug) { + if (unbalanced || vb2_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", @@ -550,76 +398,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) } /** - * __verify_planes_array() - verify that the planes array passed in struct - * v4l2_buffer from userspace can be safely used - */ -static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b) -{ - if (!V4L2_TYPE_IS_MULTIPLANAR(b->type)) - return 0; - - /* Is memory for copying plane information present? */ - if (NULL == b->m.planes) { - dprintk(1, "multi-planar buffer passed but " - "planes array not provided\n"); - return -EINVAL; - } - - if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) { - dprintk(1, "incorrect planes array length, " - "expected %d, got %d\n", vb->num_planes, b->length); - return -EINVAL; - } - - return 0; -} - -/** - * __verify_length() - Verify that the bytesused value for each plane fits in - * the plane length and that the data offset doesn't exceed the bytesused value. - */ -static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) -{ - unsigned int length; - unsigned int bytesused; - unsigned int plane; - - if (!V4L2_TYPE_IS_OUTPUT(b->type)) - return 0; - - if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { - for (plane = 0; plane < vb->num_planes; ++plane) { - length = (b->memory == V4L2_MEMORY_USERPTR || - b->memory == V4L2_MEMORY_DMABUF) - ? b->m.planes[plane].length - : vb->v4l2_planes[plane].length; - bytesused = b->m.planes[plane].bytesused - ? b->m.planes[plane].bytesused : length; - - if (b->m.planes[plane].bytesused > length) - return -EINVAL; - - if (b->m.planes[plane].data_offset > 0 && - b->m.planes[plane].data_offset >= bytesused) - return -EINVAL; - } - } else { - length = (b->memory == V4L2_MEMORY_USERPTR) - ? b->length : vb->v4l2_planes[0].length; - bytesused = b->bytesused ? b->bytesused : length; - - if (b->bytesused > length) - return -EINVAL; - } - - return 0; -} - -/** - * __buffer_in_use() - return true if the buffer is in use and + * vb2_buffer_in_use() - return true if the buffer is in use and * the queue cannot be freed (by the means of REQBUFS(0)) call */ -static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb) +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb) { unsigned int plane; for (plane = 0; plane < vb->num_planes; ++plane) { @@ -635,6 +417,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb) } return false; } +EXPORT_SYMBOL(vb2_buffer_in_use); /** * __buffers_in_use() - return true if any buffers on the queue are in use and @@ -644,122 +427,30 @@ static bool __buffers_in_use(struct vb2_queue *q) { unsigned int buffer; for (buffer = 0; buffer < q->num_buffers; ++buffer) { - if (__buffer_in_use(q, q->bufs[buffer])) + if (vb2_buffer_in_use(q, q->bufs[buffer])) return true; } return false; } /** - * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be - * returned to userspace - */ -static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) -{ - struct vb2_queue *q = vb->vb2_queue; - - /* Copy back data such as timestamp, flags, etc. */ - memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m)); - b->reserved2 = vb->v4l2_buf.reserved2; - b->reserved = vb->v4l2_buf.reserved; - - if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) { - /* - * Fill in plane-related data if userspace provided an array - * for it. The caller has already verified memory and size. - */ - b->length = vb->num_planes; - memcpy(b->m.planes, vb->v4l2_planes, - b->length * sizeof(struct v4l2_plane)); - } else { - /* - * We use length and offset in v4l2_planes array even for - * single-planar buffers, but userspace does not. - */ - b->length = vb->v4l2_planes[0].length; - b->bytesused = vb->v4l2_planes[0].bytesused; - if (q->memory == V4L2_MEMORY_MMAP) - b->m.offset = vb->v4l2_planes[0].m.mem_offset; - else if (q->memory == V4L2_MEMORY_USERPTR) - b->m.userptr = vb->v4l2_planes[0].m.userptr; - else if (q->memory == V4L2_MEMORY_DMABUF) - b->m.fd = vb->v4l2_planes[0].m.fd; - } - - /* - * Clear any buffer state related flags. - */ - 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) { - /* - * For non-COPY timestamps, drop timestamp source bits - * and obtain the timestamp source from the queue. - */ - b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - } - - switch (vb->state) { - case VB2_BUF_STATE_QUEUED: - case VB2_BUF_STATE_ACTIVE: - b->flags |= V4L2_BUF_FLAG_QUEUED; - break; - case VB2_BUF_STATE_ERROR: - b->flags |= V4L2_BUF_FLAG_ERROR; - /* fall through */ - case VB2_BUF_STATE_DONE: - b->flags |= V4L2_BUF_FLAG_DONE; - break; - case VB2_BUF_STATE_PREPARED: - b->flags |= V4L2_BUF_FLAG_PREPARED; - break; - case VB2_BUF_STATE_PREPARING: - case VB2_BUF_STATE_DEQUEUED: - case VB2_BUF_STATE_REQUEUEING: - /* nothing */ - break; - } - - if (__buffer_in_use(q, vb)) - b->flags |= V4L2_BUF_FLAG_MAPPED; -} - -/** - * vb2_querybuf() - query video buffer information + * vb2_core_querybuf() - query video buffer information * @q: videobuf queue - * @b: buffer struct passed from userspace to vidioc_querybuf handler - * in driver + * @index: id number of the buffer + * @pb: buffer struct passed from userspace * * Should be called from vidioc_querybuf ioctl handler in driver. - * This function will verify the passed v4l2_buffer structure and fill the - * relevant information for the userspace. + * 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_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb) { - struct vb2_buffer *vb; - int ret; - - if (b->type != q->type) { - dprintk(1, "wrong buffer type\n"); - return -EINVAL; - } - - if (b->index >= q->num_buffers) { - dprintk(1, "buffer index out of range\n"); - return -EINVAL; - } - vb = q->bufs[b->index]; - ret = __verify_planes_array(vb, b); - if (!ret) - __fill_v4l2_buffer(vb, b); - return ret; + return call_bufop(q, fill_user_buffer, q->bufs[index], pb); } -EXPORT_SYMBOL(vb2_querybuf); +EXPORT_SYMBOL_GPL(vb2_core_querybuf); /** * __verify_userptr_ops() - verify that all memory operations required for @@ -802,14 +493,14 @@ static int __verify_dmabuf_ops(struct vb2_queue *q) } /** - * __verify_memory_type() - Check whether the memory type and buffer type + * vb2_verify_memory_type() - Check whether the memory type and buffer type * passed to a buffer operation are compatible with the queue. */ -static int __verify_memory_type(struct vb2_queue *q, - enum v4l2_memory memory, enum v4l2_buf_type type) +int vb2_verify_memory_type(struct vb2_queue *q, + enum vb2_memory memory, unsigned int type) { - if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR && - memory != V4L2_MEMORY_DMABUF) { + if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR && + memory != VB2_MEMORY_DMABUF) { dprintk(1, "unsupported memory type\n"); return -EINVAL; } @@ -823,17 +514,17 @@ static int __verify_memory_type(struct vb2_queue *q, * Make sure all the required memory ops for given memory type * are available. */ - if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) { + if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) { dprintk(1, "MMAP for current setup unsupported\n"); return -EINVAL; } - if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) { + if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) { dprintk(1, "USERPTR for current setup unsupported\n"); return -EINVAL; } - if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) { + if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) { dprintk(1, "DMABUF for current setup unsupported\n"); return -EINVAL; } @@ -849,11 +540,13 @@ static int __verify_memory_type(struct vb2_queue *q, } return 0; } +EXPORT_SYMBOL(vb2_verify_memory_type); /** - * __reqbufs() - Initiate streaming + * vb2_core_reqbufs() - Initiate streaming * @q: videobuf2 queue - * @req: struct passed from userspace to vidioc_reqbufs handler in driver + * @memory: memory type + * @count: requested buffer count * * Should be called from vidioc_reqbufs ioctl handler of a driver. * This function: @@ -873,7 +566,8 @@ static int __verify_memory_type(struct vb2_queue *q, * The return values from this function are intended to be directly returned * from vidioc_reqbufs handler in driver. */ -static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) +int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, + unsigned int *count) { unsigned int num_buffers, allocated_buffers, num_planes = 0; int ret; @@ -883,13 +577,13 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) return -EBUSY; } - if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) { + if (*count == 0 || q->num_buffers != 0 || q->memory != memory) { /* * We already have buffers allocated, so first check if they * are not in use and can be freed. */ mutex_lock(&q->mmap_lock); - if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) { + if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) { mutex_unlock(&q->mmap_lock); dprintk(1, "memory in use, cannot free\n"); return -EBUSY; @@ -910,18 +604,18 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) * In case of REQBUFS(0) return immediately without calling * driver's queue_setup() callback and allocating resources. */ - if (req->count == 0) + if (*count == 0) return 0; } /* * Make sure the requested values and current defaults are sane. */ - num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME); + 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 = req->memory; + q->memory = memory; /* * Ask the driver how many buffers and planes per buffer it requires. @@ -933,7 +627,8 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) return ret; /* Finally, allocate buffers and video memory */ - allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes); + allocated_buffers = + __vb2_queue_alloc(q, memory, num_buffers, num_planes); if (allocated_buffers == 0) { dprintk(1, "memory allocation failed\n"); return -ENOMEM; @@ -982,31 +677,19 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) * Return the number of successfully allocated buffers * to the userspace. */ - req->count = allocated_buffers; - q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); + *count = allocated_buffers; + q->waiting_for_buffers = !q->is_output; return 0; } +EXPORT_SYMBOL_GPL(vb2_core_reqbufs); /** - * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and - * type values. + * vb2_core_create_bufs() - Allocate buffers and any required auxiliary structs * @q: videobuf2 queue - * @req: struct passed from userspace to vidioc_reqbufs handler in driver - */ -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) -{ - int ret = __verify_memory_type(q, req->memory, req->type); - - return ret ? ret : __reqbufs(q, req); -} -EXPORT_SYMBOL_GPL(vb2_reqbufs); - -/** - * __create_bufs() - Allocate buffers and any required auxiliary structs - * @q: videobuf2 queue - * @create: creation parameters, passed from userspace to vidioc_create_bufs - * handler in driver + * @memory: memory type + * @count: requested buffer count + * @parg: parameter passed to device driver * * Should be called from vidioc_create_bufs ioctl handler of a driver. * This function: @@ -1017,12 +700,13 @@ EXPORT_SYMBOL_GPL(vb2_reqbufs); * The return values from this function are intended to be directly returned * from vidioc_create_bufs handler in driver. */ -static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) +int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, + unsigned int *count, const void *parg) { unsigned int num_planes = 0, num_buffers, allocated_buffers; int ret; - if (q->num_buffers == VIDEO_MAX_FRAME) { + if (q->num_buffers == VB2_MAX_FRAME) { dprintk(1, "maximum number of buffers already allocated\n"); return -ENOBUFS; } @@ -1030,23 +714,23 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create if (!q->num_buffers) { memset(q->plane_sizes, 0, sizeof(q->plane_sizes)); memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); - q->memory = create->memory; - q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); + q->memory = memory; + q->waiting_for_buffers = !q->is_output; } - num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers); + num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers); /* * Ask the driver, whether the requested number of buffers, planes per * buffer and their sizes are acceptable */ - ret = call_qop(q, queue_setup, q, &create->format, &num_buffers, + ret = call_qop(q, queue_setup, q, parg, &num_buffers, &num_planes, q->plane_sizes, q->alloc_ctx); if (ret) return ret; /* Finally, allocate buffers and video memory */ - allocated_buffers = __vb2_queue_alloc(q, create->memory, num_buffers, + allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers, num_planes); if (allocated_buffers == 0) { dprintk(1, "memory allocation failed\n"); @@ -1063,7 +747,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create * q->num_buffers contains the total number of buffers, that the * queue driver has set up */ - ret = call_qop(q, queue_setup, q, &create->format, &num_buffers, + ret = call_qop(q, queue_setup, q, parg, &num_buffers, &num_planes, q->plane_sizes, q->alloc_ctx); if (!ret && allocated_buffers < num_buffers) @@ -1093,28 +777,11 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create * Return the number of successfully allocated buffers * to the userspace. */ - create->count = allocated_buffers; + *count = allocated_buffers; return 0; } - -/** - * vb2_create_bufs() - Wrapper for __create_bufs() that also verifies the - * memory and type values. - * @q: videobuf2 queue - * @create: creation parameters, passed from userspace to vidioc_create_bufs - * handler in driver - */ -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) -{ - int ret = __verify_memory_type(q, create->memory, create->format.type); - - create->index = q->num_buffers; - if (create->count == 0) - return ret != -EBUSY ? ret : 0; - return ret ? ret : __create_bufs(q, create); -} -EXPORT_SYMBOL_GPL(vb2_create_bufs); +EXPORT_SYMBOL_GPL(vb2_core_create_bufs); /** * vb2_plane_vaddr() - Return a kernel virtual address of a given plane @@ -1197,7 +864,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) vb->cnt_buf_done++; #endif dprintk(4, "done processing on buffer %d, state: %d\n", - vb->v4l2_buf.index, state); + vb->index, state); /* sync buffers */ for (plane = 0; plane < vb->num_planes; ++plane) @@ -1256,182 +923,41 @@ void vb2_discard_done(struct vb2_queue *q) } EXPORT_SYMBOL_GPL(vb2_discard_done); -static void vb2_warn_zero_bytesused(struct vb2_buffer *vb) -{ - static bool check_once; - - if (check_once) - return; - - check_once = true; - WARN_ON(1); - - pr_warn("use of bytesused == 0 is deprecated and will be removed in the future,\n"); - if (vb->vb2_queue->allow_zero_bytesused) - pr_warn("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n"); - else - pr_warn("use the actual size instead.\n"); -} - -/** - * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a - * v4l2_buffer by the userspace. The caller has already verified that struct - * v4l2_buffer has a valid number of planes. - */ -static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b, - struct v4l2_plane *v4l2_planes) -{ - unsigned int plane; - - if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { - if (b->memory == V4L2_MEMORY_USERPTR) { - for (plane = 0; plane < vb->num_planes; ++plane) { - v4l2_planes[plane].m.userptr = - b->m.planes[plane].m.userptr; - v4l2_planes[plane].length = - b->m.planes[plane].length; - } - } - if (b->memory == V4L2_MEMORY_DMABUF) { - for (plane = 0; plane < vb->num_planes; ++plane) { - v4l2_planes[plane].m.fd = - b->m.planes[plane].m.fd; - v4l2_planes[plane].length = - b->m.planes[plane].length; - } - } - - /* Fill in driver-provided information for OUTPUT types */ - if (V4L2_TYPE_IS_OUTPUT(b->type)) { - /* - * Will have to go up to b->length when API starts - * accepting variable number of planes. - * - * If bytesused == 0 for the output buffer, then fall - * back to the full buffer size. In that case - * userspace clearly never bothered to set it and - * it's a safe assumption that they really meant to - * use the full plane sizes. - * - * Some drivers, e.g. old codec drivers, use bytesused == 0 - * as a way to indicate that streaming is finished. - * In that case, the driver should use the - * allow_zero_bytesused flag to keep old userspace - * applications working. - */ - for (plane = 0; plane < vb->num_planes; ++plane) { - struct v4l2_plane *pdst = &v4l2_planes[plane]; - struct v4l2_plane *psrc = &b->m.planes[plane]; - - if (psrc->bytesused == 0) - vb2_warn_zero_bytesused(vb); - - if (vb->vb2_queue->allow_zero_bytesused) - pdst->bytesused = psrc->bytesused; - else - pdst->bytesused = psrc->bytesused ? - psrc->bytesused : pdst->length; - pdst->data_offset = psrc->data_offset; - } - } - } else { - /* - * Single-planar buffers do not use planes array, - * so fill in relevant v4l2_buffer struct fields instead. - * In videobuf we use our internal V4l2_planes struct for - * single-planar buffers as well, for simplicity. - * - * If bytesused == 0 for the output buffer, then fall back - * to the full buffer size as that's a sensible default. - * - * Some drivers, e.g. old codec drivers, use bytesused == 0 as - * a way to indicate that streaming is finished. In that case, - * the driver should use the allow_zero_bytesused flag to keep - * old userspace applications working. - */ - if (b->memory == V4L2_MEMORY_USERPTR) { - v4l2_planes[0].m.userptr = b->m.userptr; - v4l2_planes[0].length = b->length; - } - - if (b->memory == V4L2_MEMORY_DMABUF) { - v4l2_planes[0].m.fd = b->m.fd; - v4l2_planes[0].length = b->length; - } - - if (V4L2_TYPE_IS_OUTPUT(b->type)) { - if (b->bytesused == 0) - vb2_warn_zero_bytesused(vb); - - if (vb->vb2_queue->allow_zero_bytesused) - v4l2_planes[0].bytesused = b->bytesused; - else - v4l2_planes[0].bytesused = b->bytesused ? - b->bytesused : v4l2_planes[0].length; - } else - v4l2_planes[0].bytesused = 0; - - } - - /* Zero flags that the vb2 core handles */ - vb->v4l2_buf.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)) { - /* - * Non-COPY timestamps and non-OUTPUT queues will get - * their timestamp and timestamp source flags from the - * queue. - */ - vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - } - - if (V4L2_TYPE_IS_OUTPUT(b->type)) { - /* - * For output buffers mask out the timecode flag: - * this will be handled later in vb2_internal_qbuf(). - * The 'field' is valid metadata for this output buffer - * and so that needs to be copied here. - */ - vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TIMECODE; - vb->v4l2_buf.field = b->field; - } else { - /* Zero any output buffer flags as this is a capture buffer */ - vb->v4l2_buf.flags &= ~V4L2_BUFFER_OUT_FLAGS; - } -} - /** * __qbuf_mmap() - handle qbuf of an MMAP buffer */ -static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b) +static int __qbuf_mmap(struct vb2_buffer *vb, const void *pb) { - __fill_vb2_buffer(vb, b, vb->v4l2_planes); - return call_vb_qop(vb, buf_prepare, vb); + int ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, + vb, pb, vb->planes); + return ret ? ret : call_vb_qop(vb, buf_prepare, vb); } /** * __qbuf_userptr() - handle qbuf of a USERPTR buffer */ -static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) +static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) { - struct v4l2_plane planes[VIDEO_MAX_PLANES]; + struct vb2_plane planes[VB2_MAX_PLANES]; struct vb2_queue *q = vb->vb2_queue; void *mem_priv; unsigned int plane; int ret; enum dma_data_direction dma_dir = - V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); /* Copy relevant information provided by the userspace */ - __fill_vb2_buffer(vb, b, planes); + ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes); + if (ret) + return ret; for (plane = 0; plane < vb->num_planes; ++plane) { /* Skip the plane if already verified */ - if (vb->v4l2_planes[plane].m.userptr && - vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr - && vb->v4l2_planes[plane].length == planes[plane].length) + if (vb->planes[plane].m.userptr && + vb->planes[plane].m.userptr == planes[plane].m.userptr + && vb->planes[plane].length == planes[plane].length) continue; dprintk(3, "userspace address for plane %d changed, " @@ -1457,7 +983,10 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) } vb->planes[plane].mem_priv = NULL; - memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane)); + vb->planes[plane].bytesused = 0; + vb->planes[plane].length = 0; + vb->planes[plane].m.userptr = 0; + vb->planes[plane].data_offset = 0; /* Acquire each plane's memory */ mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_ctx[plane], @@ -1476,8 +1005,12 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) * Now that everything is in order, copy relevant information * provided by userspace. */ - for (plane = 0; plane < vb->num_planes; ++plane) - vb->v4l2_planes[plane] = planes[plane]; + for (plane = 0; plane < vb->num_planes; ++plane) { + vb->planes[plane].bytesused = planes[plane].bytesused; + vb->planes[plane].length = planes[plane].length; + vb->planes[plane].m.userptr = planes[plane].m.userptr; + vb->planes[plane].data_offset = planes[plane].data_offset; + } if (reacquired) { /* @@ -1504,10 +1037,11 @@ err: /* In case of errors, release planes that were already acquired */ for (plane = 0; plane < vb->num_planes; ++plane) { if (vb->planes[plane].mem_priv) - call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv); + call_void_memop(vb, put_userptr, + vb->planes[plane].mem_priv); vb->planes[plane].mem_priv = NULL; - vb->v4l2_planes[plane].m.userptr = 0; - vb->v4l2_planes[plane].length = 0; + vb->planes[plane].m.userptr = 0; + vb->planes[plane].length = 0; } return ret; @@ -1516,20 +1050,22 @@ err: /** * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer */ -static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) +static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) { - struct v4l2_plane planes[VIDEO_MAX_PLANES]; + struct vb2_plane planes[VB2_MAX_PLANES]; struct vb2_queue *q = vb->vb2_queue; void *mem_priv; unsigned int plane; int ret; enum dma_data_direction dma_dir = - V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); /* Copy relevant information provided by the userspace */ - __fill_vb2_buffer(vb, b, planes); + ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes); + if (ret) + return ret; for (plane = 0; plane < vb->num_planes; ++plane) { struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd); @@ -1554,7 +1090,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) /* Skip the plane if already verified */ if (dbuf == vb->planes[plane].dbuf && - vb->v4l2_planes[plane].length == planes[plane].length) { + vb->planes[plane].length == planes[plane].length) { dma_buf_put(dbuf); continue; } @@ -1568,11 +1104,15 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) /* Release previously acquired memory if present */ __vb2_plane_dmabuf_put(vb, &vb->planes[plane]); - memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane)); + vb->planes[plane].bytesused = 0; + vb->planes[plane].length = 0; + vb->planes[plane].m.fd = 0; + vb->planes[plane].data_offset = 0; /* Acquire each plane's memory */ - mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane], - dbuf, planes[plane].length, dma_dir); + mem_priv = call_ptr_memop(vb, attach_dmabuf, + q->alloc_ctx[plane], dbuf, planes[plane].length, + dma_dir); if (IS_ERR(mem_priv)) { dprintk(1, "failed to attach dmabuf\n"); ret = PTR_ERR(mem_priv); @@ -1602,8 +1142,12 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) * Now that everything is in order, copy relevant information * provided by userspace. */ - for (plane = 0; plane < vb->num_planes; ++plane) - vb->v4l2_planes[plane] = planes[plane]; + for (plane = 0; plane < vb->num_planes; ++plane) { + vb->planes[plane].bytesused = planes[plane].bytesused; + vb->planes[plane].length = planes[plane].length; + vb->planes[plane].m.fd = planes[plane].m.fd; + vb->planes[plane].data_offset = planes[plane].data_offset; + } if (reacquired) { /* @@ -1652,49 +1196,27 @@ static void __enqueue_in_driver(struct vb2_buffer *vb) call_void_vb_qop(vb, buf_queue, vb); } -static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) +static int __buf_prepare(struct vb2_buffer *vb, const void *pb) { struct vb2_queue *q = vb->vb2_queue; int ret; - ret = __verify_length(vb, b); - if (ret < 0) { - dprintk(1, "plane parameters verification failed: %d\n", ret); - return ret; - } - if (b->field == V4L2_FIELD_ALTERNATE && V4L2_TYPE_IS_OUTPUT(q->type)) { - /* - * If the format's field is ALTERNATE, then the buffer's field - * should be either TOP or BOTTOM, not ALTERNATE since that - * makes no sense. The driver has to know whether the - * buffer represents a top or a bottom field in order to - * program any DMA correctly. Using ALTERNATE is wrong, since - * that just says that it is either a top or a bottom field, - * but not which of the two it is. - */ - dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n"); - return -EINVAL; - } - if (q->error) { dprintk(1, "fatal error occurred on queue\n"); return -EIO; } vb->state = VB2_BUF_STATE_PREPARING; - vb->v4l2_buf.timestamp.tv_sec = 0; - vb->v4l2_buf.timestamp.tv_usec = 0; - vb->v4l2_buf.sequence = 0; switch (q->memory) { - case V4L2_MEMORY_MMAP: - ret = __qbuf_mmap(vb, b); + case VB2_MEMORY_MMAP: + ret = __qbuf_mmap(vb, pb); break; - case V4L2_MEMORY_USERPTR: - ret = __qbuf_userptr(vb, b); + case VB2_MEMORY_USERPTR: + ret = __qbuf_userptr(vb, pb); break; - case V4L2_MEMORY_DMABUF: - ret = __qbuf_dmabuf(vb, b); + case VB2_MEMORY_DMABUF: + ret = __qbuf_dmabuf(vb, pb); break; default: WARN(1, "Invalid queue type\n"); @@ -1708,79 +1230,48 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) return ret; } -static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, - const char *opname) -{ - if (b->type != q->type) { - dprintk(1, "%s: invalid buffer type\n", opname); - return -EINVAL; - } - - if (b->index >= q->num_buffers) { - dprintk(1, "%s: buffer index out of range\n", opname); - return -EINVAL; - } - - if (q->bufs[b->index] == NULL) { - /* Should never happen */ - dprintk(1, "%s: buffer is NULL\n", opname); - return -EINVAL; - } - - if (b->memory != q->memory) { - dprintk(1, "%s: invalid memory type\n", opname); - return -EINVAL; - } - - return __verify_planes_array(q->bufs[b->index], b); -} - /** - * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel + * vb2_core_prepare_buf() - Pass ownership of a buffer from userspace + * to the kernel * @q: videobuf2 queue - * @b: buffer structure passed from userspace to vidioc_prepare_buf + * @index: id number of the buffer + * @pb: buffer structure passed from userspace to vidioc_prepare_buf * handler in driver * * Should be called from vidioc_prepare_buf ioctl handler of a driver. - * This function: - * 1) verifies the passed buffer, - * 2) calls buf_prepare callback in the driver (if provided), in which - * driver-specific buffer initialization can be performed, + * The passed buffer should have been verified. + * This function calls buf_prepare callback in the driver (if provided), + * in which driver-specific buffer initialization can be performed, * * The return values from this function are intended to be directly returned * from vidioc_prepare_buf handler in driver. */ -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b) +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb) { struct vb2_buffer *vb; int ret; - if (vb2_fileio_is_active(q)) { - dprintk(1, "file io in progress\n"); - return -EBUSY; - } - - ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf"); - if (ret) - return ret; - - vb = q->bufs[b->index]; + vb = q->bufs[index]; if (vb->state != VB2_BUF_STATE_DEQUEUED) { dprintk(1, "invalid buffer state %d\n", vb->state); return -EINVAL; } - ret = __buf_prepare(vb, b); - if (!ret) { - /* Fill buffer information for the userspace */ - __fill_v4l2_buffer(vb, b); + ret = __buf_prepare(vb, pb); + if (ret) + return ret; + + /* Fill buffer information for the userspace */ + ret = call_bufop(q, fill_user_buffer, vb, pb); + if (ret) + return ret; + + dprintk(1, "prepare of buffer %d succeeded\n", vb->index); - dprintk(1, "prepare of buffer %d succeeded\n", vb->v4l2_buf.index); - } return ret; } -EXPORT_SYMBOL_GPL(vb2_prepare_buf); +EXPORT_SYMBOL_GPL(vb2_core_prepare_buf); /** * vb2_start_streaming() - Attempt to start streaming. @@ -1845,19 +1336,34 @@ static int vb2_start_streaming(struct vb2_queue *q) return ret; } -static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) +/** + * vb2_core_qbuf() - Queue a buffer from userspace + * @q: videobuf2 queue + * @index: id number of the buffer + * @pb: buffer structure passed from userspace to vidioc_qbuf handler + * in driver + * + * Should be called from vidioc_qbuf ioctl handler of a driver. + * The passed buffer should have been verified. + * This function: + * 1) if necessary, calls buf_prepare callback in the driver (if provided), in + * which driver-specific buffer initialization can be performed, + * 2) if streaming is on, queues the buffer in driver by the means of buf_queue + * callback for processing. + * + * The return values from this function are intended to be directly returned + * from vidioc_qbuf handler in driver. + */ +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) { - int ret = vb2_queue_or_prepare_buf(q, b, "qbuf"); struct vb2_buffer *vb; + int ret; - if (ret) - return ret; - - vb = q->bufs[b->index]; + vb = q->bufs[index]; switch (vb->state) { case VB2_BUF_STATE_DEQUEUED: - ret = __buf_prepare(vb, b); + ret = __buf_prepare(vb, pb); if (ret) return ret; break; @@ -1879,18 +1385,8 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) q->queued_count++; q->waiting_for_buffers = false; vb->state = VB2_BUF_STATE_QUEUED; - if (V4L2_TYPE_IS_OUTPUT(q->type)) { - /* - * 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) - vb->v4l2_buf.timestamp = b->timestamp; - vb->v4l2_buf.flags |= b->flags & V4L2_BUF_FLAG_TIMECODE; - if (b->flags & V4L2_BUF_FLAG_TIMECODE) - vb->v4l2_buf.timecode = b->timecode; - } + + call_bufop(q, set_timestamp, vb, pb); trace_vb2_qbuf(q, vb); @@ -1902,7 +1398,9 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) __enqueue_in_driver(vb); /* Fill buffer information for the userspace */ - __fill_v4l2_buffer(vb, b); + ret = call_bufop(q, fill_user_buffer, vb, pb); + if (ret) + return ret; /* * If streamon has been called, and we haven't yet called @@ -1917,37 +1415,10 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) return ret; } - dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index); + dprintk(1, "qbuf of buffer %d succeeded\n", vb->index); return 0; } - -/** - * vb2_qbuf() - Queue a buffer from userspace - * @q: videobuf2 queue - * @b: buffer structure passed from userspace to vidioc_qbuf handler - * in driver - * - * Should be called from vidioc_qbuf ioctl handler of a driver. - * This function: - * 1) verifies the passed buffer, - * 2) if necessary, calls buf_prepare callback in the driver (if provided), in - * which driver-specific buffer initialization can be performed, - * 3) if streaming is on, queues the buffer in driver by the means of buf_queue - * callback for processing. - * - * The return values from this function are intended to be directly returned - * from vidioc_qbuf handler in driver. - */ -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) -{ - if (vb2_fileio_is_active(q)) { - dprintk(1, "file io in progress\n"); - return -EBUSY; - } - - return vb2_internal_qbuf(q, b); -} -EXPORT_SYMBOL_GPL(vb2_qbuf); +EXPORT_SYMBOL_GPL(vb2_core_qbuf); /** * __vb2_wait_for_done_vb() - wait for a buffer to become available @@ -2031,7 +1502,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) * Will sleep if required for nonblocking == false. */ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb, - struct v4l2_buffer *b, int nonblocking) + int nonblocking) { unsigned long flags; int ret; @@ -2052,10 +1523,10 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb, /* * Only remove the buffer from done_list if v4l2_buffer can handle all * the planes. + * Verifying planes is NOT necessary since it already has been checked + * before the buffer is queued/prepared. So it can never fail. */ - ret = __verify_planes_array(*vb, b); - if (!ret) - list_del(&(*vb)->done_entry); + list_del(&(*vb)->done_entry); spin_unlock_irqrestore(&q->done_lock, flags); return ret; @@ -2098,7 +1569,7 @@ static void __vb2_dqbuf(struct vb2_buffer *vb) vb->state = VB2_BUF_STATE_DEQUEUED; /* unmap DMABUF buffer */ - if (q->memory == V4L2_MEMORY_DMABUF) + if (q->memory == VB2_MEMORY_DMABUF) for (i = 0; i < vb->num_planes; ++i) { if (!vb->planes[i].dbuf_mapped) continue; @@ -2107,16 +1578,33 @@ static void __vb2_dqbuf(struct vb2_buffer *vb) } } -static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) +/** + * vb2_dqbuf() - Dequeue a buffer to the userspace + * @q: videobuf2 queue + * @pb: buffer structure passed from userspace to vidioc_dqbuf handler + * in driver + * @nonblocking: if true, this call will not sleep waiting for a buffer if no + * buffers ready for dequeuing are present. Normally the driver + * would be passing (file->f_flags & O_NONBLOCK) here + * + * Should be called from vidioc_dqbuf ioctl handler of a driver. + * The passed buffer should have been verified. + * This function: + * 1) calls buf_finish callback in the driver (if provided), in which + * driver can perform any additional operations that may be required before + * returning the buffer to userspace, such as cache sync, + * 2) the buffer struct members are filled with relevant information for + * the userspace. + * + * The return values from this function are intended to be directly returned + * from vidioc_dqbuf handler in driver. + */ +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking) { struct vb2_buffer *vb = NULL; int ret; - if (b->type != q->type) { - dprintk(1, "invalid buffer type\n"); - return -EINVAL; - } - ret = __vb2_get_done_vb(q, &vb, b, nonblocking); + ret = __vb2_get_done_vb(q, &vb, nonblocking); if (ret < 0) return ret; @@ -2135,55 +1623,26 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool n call_void_vb_qop(vb, buf_finish, vb); /* Fill buffer information for the userspace */ - __fill_v4l2_buffer(vb, b); + ret = call_bufop(q, fill_user_buffer, vb, pb); + if (ret) + return ret; + /* Remove from videobuf queue */ list_del(&vb->queued_entry); q->queued_count--; trace_vb2_dqbuf(q, vb); - if (!V4L2_TYPE_IS_OUTPUT(q->type) && - vb->v4l2_buf.flags & V4L2_BUF_FLAG_LAST) - q->last_buffer_dequeued = true; /* go back to dequeued state */ __vb2_dqbuf(vb); dprintk(1, "dqbuf of buffer %d, with state %d\n", - vb->v4l2_buf.index, vb->state); + vb->index, vb->state); return 0; -} -/** - * vb2_dqbuf() - Dequeue a buffer to the userspace - * @q: videobuf2 queue - * @b: buffer structure passed from userspace to vidioc_dqbuf handler - * in driver - * @nonblocking: if true, this call will not sleep waiting for a buffer if no - * buffers ready for dequeuing are present. Normally the driver - * would be passing (file->f_flags & O_NONBLOCK) here - * - * Should be called from vidioc_dqbuf ioctl handler of a driver. - * This function: - * 1) verifies the passed buffer, - * 2) calls buf_finish callback in the driver (if provided), in which - * driver can perform any additional operations that may be required before - * returning the buffer to userspace, such as cache sync, - * 3) the buffer struct members are filled with relevant information for - * the userspace. - * - * The return values from this function are intended to be directly returned - * from vidioc_dqbuf handler in driver. - */ -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) -{ - if (vb2_fileio_is_active(q)) { - dprintk(1, "file io in progress\n"); - return -EBUSY; - } - return vb2_internal_dqbuf(q, b, nonblocking); } -EXPORT_SYMBOL_GPL(vb2_dqbuf); +EXPORT_SYMBOL_GPL(vb2_core_dqbuf); /** * __vb2_queue_cancel() - cancel and stop (pause) streaming @@ -2253,7 +1712,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q) } } -static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type) +int vb2_core_streamon(struct vb2_queue *q, unsigned int type) { int ret; @@ -2295,6 +1754,7 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type) dprintk(3, "successful\n"); return 0; } +EXPORT_SYMBOL_GPL(vb2_core_streamon); /** * vb2_queue_error() - signal a fatal error on the queue @@ -2317,30 +1777,7 @@ void vb2_queue_error(struct vb2_queue *q) } EXPORT_SYMBOL_GPL(vb2_queue_error); -/** - * vb2_streamon - start streaming - * @q: videobuf2 queue - * @type: type argument passed from userspace to vidioc_streamon handler - * - * Should be called from vidioc_streamon handler of a driver. - * This function: - * 1) verifies current state - * 2) passes any previously queued buffers to the driver and starts streaming - * - * The return values from this function are intended to be directly returned - * from vidioc_streamon handler in the driver. - */ -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type) -{ - if (vb2_fileio_is_active(q)) { - dprintk(1, "file io in progress\n"); - return -EBUSY; - } - return vb2_internal_streamon(q, type); -} -EXPORT_SYMBOL_GPL(vb2_streamon); - -static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) +int vb2_core_streamoff(struct vb2_queue *q, unsigned int type) { if (type != q->type) { dprintk(1, "invalid stream type\n"); @@ -2357,37 +1794,13 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) * their normal dequeued state. */ __vb2_queue_cancel(q); - q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); + q->waiting_for_buffers = !q->is_output; q->last_buffer_dequeued = false; dprintk(3, "successful\n"); return 0; } - -/** - * vb2_streamoff - stop streaming - * @q: videobuf2 queue - * @type: type argument passed from userspace to vidioc_streamoff handler - * - * Should be called from vidioc_streamoff handler of a driver. - * This function: - * 1) verifies current state, - * 2) stop streaming and dequeues any queued buffers, including those previously - * passed to the driver (after waiting for the driver to finish). - * - * This call can be used for pausing playback. - * The return values from this function are intended to be directly returned - * from vidioc_streamoff handler in the driver - */ -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) -{ - if (vb2_fileio_is_active(q)) { - dprintk(1, "file io in progress\n"); - return -EBUSY; - } - return vb2_internal_streamoff(q, type); -} -EXPORT_SYMBOL_GPL(vb2_streamoff); +EXPORT_SYMBOL_GPL(vb2_core_streamoff); /** * __find_plane_by_offset() - find plane associated with the given offset off @@ -2407,7 +1820,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off, vb = q->bufs[buffer]; for (plane = 0; plane < vb->num_planes; ++plane) { - if (vb->v4l2_planes[plane].m.mem_offset == off) { + if (vb->planes[plane].m.offset == off) { *_buffer = buffer; *_plane = plane; return 0; @@ -2419,22 +1832,27 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off, } /** - * vb2_expbuf() - Export a buffer as a file descriptor + * vb2_core_expbuf() - Export a buffer as a file descriptor * @q: videobuf2 queue - * @eb: export buffer structure passed from userspace to vidioc_expbuf - * handler in driver + * @fd: file descriptor associated with DMABUF (set by driver) * + * @type: buffer type + * @index: id number of the buffer + * @plane: index of the plane to be exported, 0 for single plane queues + * @flags: flags for newly created file, currently only O_CLOEXEC is + * supported, refer to manual of open syscall for more details * * The return values from this function are intended to be directly returned * from vidioc_expbuf handler in driver. */ -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type, + unsigned int index, unsigned int plane, unsigned int flags) { struct vb2_buffer *vb = NULL; struct vb2_plane *vb_plane; int ret; struct dma_buf *dbuf; - if (q->memory != V4L2_MEMORY_MMAP) { + if (q->memory != VB2_MEMORY_MMAP) { dprintk(1, "queue is not currently set up for mmap\n"); return -EINVAL; } @@ -2444,24 +1862,24 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) return -EINVAL; } - if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) { + if (flags & ~(O_CLOEXEC | O_ACCMODE)) { dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n"); return -EINVAL; } - if (eb->type != q->type) { + if (type != q->type) { dprintk(1, "invalid buffer type\n"); return -EINVAL; } - if (eb->index >= q->num_buffers) { + if (index >= q->num_buffers) { dprintk(1, "buffer index out of range\n"); return -EINVAL; } - vb = q->bufs[eb->index]; + vb = q->bufs[index]; - if (eb->plane >= vb->num_planes) { + if (plane >= vb->num_planes) { dprintk(1, "buffer plane out of range\n"); return -EINVAL; } @@ -2471,30 +1889,31 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) return -EBUSY; } - vb_plane = &vb->planes[eb->plane]; + vb_plane = &vb->planes[plane]; - dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE); + dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, + flags & O_ACCMODE); if (IS_ERR_OR_NULL(dbuf)) { dprintk(1, "failed to export buffer %d, plane %d\n", - eb->index, eb->plane); + index, plane); return -EINVAL; } - ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE); + ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE); if (ret < 0) { dprintk(3, "buffer %d, plane %d failed to export (%d)\n", - eb->index, eb->plane, ret); + index, plane, ret); dma_buf_put(dbuf); return ret; } dprintk(3, "buffer %d, plane %d exported as %d descriptor\n", - eb->index, eb->plane, ret); - eb->fd = ret; + index, plane, ret); + *fd = ret; return 0; } -EXPORT_SYMBOL_GPL(vb2_expbuf); +EXPORT_SYMBOL_GPL(vb2_core_expbuf); /** * vb2_mmap() - map video buffers into application address space @@ -2523,7 +1942,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) int ret; unsigned long length; - if (q->memory != V4L2_MEMORY_MMAP) { + if (q->memory != VB2_MEMORY_MMAP) { dprintk(1, "queue is not currently set up for mmap\n"); return -EINVAL; } @@ -2535,7 +1954,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) dprintk(1, "invalid vma flags, VM_SHARED needed\n"); return -EINVAL; } - if (V4L2_TYPE_IS_OUTPUT(q->type)) { + if (q->is_output) { if (!(vma->vm_flags & VM_WRITE)) { dprintk(1, "invalid vma flags, VM_WRITE needed\n"); return -EINVAL; @@ -2565,7 +1984,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) * The buffer length was page_aligned at __vb2_buf_mem_alloc(), * so, we need to do the same here. */ - length = PAGE_ALIGN(vb->v4l2_planes[plane].length); + length = PAGE_ALIGN(vb->planes[plane].length); if (length < (vma->vm_end - vma->vm_start)) { dprintk(1, "MMAP invalid, as it would overflow buffer length\n"); @@ -2596,7 +2015,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q, void *vaddr; int ret; - if (q->memory != V4L2_MEMORY_MMAP) { + if (q->memory != VB2_MEMORY_MMAP) { dprintk(1, "queue is not currently set up for mmap\n"); return -EINVAL; } @@ -2616,123 +2035,8 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q, EXPORT_SYMBOL_GPL(vb2_get_unmapped_area); #endif -static int __vb2_init_fileio(struct vb2_queue *q, int read); -static int __vb2_cleanup_fileio(struct vb2_queue *q); - -/** - * vb2_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. - * - * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any - * pending events. - * - * The return values from this function are intended to be directly returned - * from poll handler in driver. - */ -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; - - if (v4l2_event_pending(fh)) - res = POLLPRI; - else if (req_events & POLLPRI) - poll_wait(file, &fh->wait, wait); - } - - if (!V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLIN | POLLRDNORM))) - return res; - if (V4L2_TYPE_IS_OUTPUT(q->type) && !(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 (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) && - (req_events & (POLLIN | POLLRDNORM))) { - if (__vb2_init_fileio(q, 1)) - return res | POLLERR; - } - if (V4L2_TYPE_IS_OUTPUT(q->type) && (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 (V4L2_TYPE_IS_OUTPUT(q->type) && 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); - } - - /* - * 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 (V4L2_TYPE_IS_OUTPUT(q->type)) ? - res | POLLOUT | POLLWRNORM : - res | POLLIN | POLLRDNORM; - } - return res; -} -EXPORT_SYMBOL_GPL(vb2_poll); - /** - * vb2_queue_init() - initialize a videobuf2 queue + * vb2_core_queue_init() - initialize a videobuf2 queue * @q: videobuf2 queue; this structure should be allocated in driver * * The vb2_queue structure should be allocated by the driver. The driver is @@ -2742,7 +2046,7 @@ EXPORT_SYMBOL_GPL(vb2_poll); * to the struct vb2_queue description in include/media/videobuf2-core.h * for more information. */ -int vb2_queue_init(struct vb2_queue *q) +int vb2_core_queue_init(struct vb2_queue *q) { /* * Sanity check @@ -2753,16 +2057,9 @@ int vb2_queue_init(struct vb2_queue *q) WARN_ON(!q->type) || WARN_ON(!q->io_modes) || WARN_ON(!q->ops->queue_setup) || - WARN_ON(!q->ops->buf_queue) || - WARN_ON(q->timestamp_flags & - ~(V4L2_BUF_FLAG_TIMESTAMP_MASK | - V4L2_BUF_FLAG_TSTAMP_SRC_MASK))) + WARN_ON(!q->ops->buf_queue)) return -EINVAL; - /* Warn that the driver should choose an appropriate timestamp type */ - WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == - V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN); - INIT_LIST_HEAD(&q->queued_list); INIT_LIST_HEAD(&q->done_list); spin_lock_init(&q->done_lock); @@ -2774,819 +2071,24 @@ int vb2_queue_init(struct vb2_queue *q) return 0; } -EXPORT_SYMBOL_GPL(vb2_queue_init); +EXPORT_SYMBOL_GPL(vb2_core_queue_init); /** - * vb2_queue_release() - stop streaming, release the queue and free memory + * vb2_core_queue_release() - stop streaming, release the queue and free memory * @q: videobuf2 queue * * This function stops streaming and performs necessary clean ups, including * freeing video buffer memory. The driver is responsible for freeing * the vb2_queue structure itself. */ -void vb2_queue_release(struct vb2_queue *q) +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); mutex_unlock(&q->mmap_lock); } -EXPORT_SYMBOL_GPL(vb2_queue_release); - -/** - * 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[VIDEO_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 = V4L2_MEMORY_MMAP; - fileio->req.type = q->type; - q->fileio = fileio; - ret = __reqbufs(q, &fileio->req); - 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 = V4L2_TYPE_IS_MULTIPLANAR(q->type); - - /* - * 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_internal_streamon(q, q->type); - if (ret) - goto err_reqbufs; - - return ret; - -err_reqbufs: - fileio->req.count = 0; - __reqbufs(q, &fileio->req); - -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_internal_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 = V4L2_TYPE_IS_MULTIPLANAR(q->type); - /* - * 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 (V4L2_TYPE_IS_OUTPUT(q->type)) { - 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, !V4L2_TYPE_IS_OUTPUT(q->type)); - 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 - * and struct vb2_ops. - * They contain boilerplate code that most if not all drivers have to do - * and so they simplify the driver code. - */ - -/* The queue is busy if there is a owner and you are not that owner. */ -static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file) -{ - return vdev->queue->owner && vdev->queue->owner != file->private_data; -} - -/* vb2 ioctl helpers */ - -int vb2_ioctl_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *p) -{ - struct video_device *vdev = video_devdata(file); - int res = __verify_memory_type(vdev->queue, p->memory, p->type); - - if (res) - return res; - if (vb2_queue_is_busy(vdev, file)) - return -EBUSY; - res = __reqbufs(vdev->queue, p); - /* If count == 0, then the owner has released all buffers and he - is no longer owner of the queue. Otherwise we have a new owner. */ - if (res == 0) - vdev->queue->owner = p->count ? file->private_data : NULL; - return res; -} -EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs); - -int vb2_ioctl_create_bufs(struct file *file, void *priv, - struct v4l2_create_buffers *p) -{ - struct video_device *vdev = video_devdata(file); - int res = __verify_memory_type(vdev->queue, p->memory, p->format.type); - - p->index = vdev->queue->num_buffers; - /* If count == 0, then just check if memory and type are valid. - Any -EBUSY result from __verify_memory_type can be mapped to 0. */ - if (p->count == 0) - return res != -EBUSY ? res : 0; - if (res) - return res; - if (vb2_queue_is_busy(vdev, file)) - return -EBUSY; - res = __create_bufs(vdev->queue, p); - if (res == 0) - vdev->queue->owner = file->private_data; - return res; -} -EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs); - -int vb2_ioctl_prepare_buf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct video_device *vdev = video_devdata(file); - - if (vb2_queue_is_busy(vdev, file)) - return -EBUSY; - return vb2_prepare_buf(vdev->queue, p); -} -EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf); - -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct video_device *vdev = video_devdata(file); - - /* No need to call vb2_queue_is_busy(), anyone can query buffers. */ - return vb2_querybuf(vdev->queue, p); -} -EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf); - -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct video_device *vdev = video_devdata(file); - - if (vb2_queue_is_busy(vdev, file)) - return -EBUSY; - return vb2_qbuf(vdev->queue, p); -} -EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf); - -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct video_device *vdev = video_devdata(file); - - if (vb2_queue_is_busy(vdev, file)) - return -EBUSY; - return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK); -} -EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf); - -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct video_device *vdev = video_devdata(file); - - if (vb2_queue_is_busy(vdev, file)) - return -EBUSY; - return vb2_streamon(vdev->queue, i); -} -EXPORT_SYMBOL_GPL(vb2_ioctl_streamon); - -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct video_device *vdev = video_devdata(file); - - if (vb2_queue_is_busy(vdev, file)) - return -EBUSY; - return vb2_streamoff(vdev->queue, i); -} -EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff); - -int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p) -{ - struct video_device *vdev = video_devdata(file); - - if (vb2_queue_is_busy(vdev, file)) - return -EBUSY; - return vb2_expbuf(vdev->queue, p); -} -EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf); - -/* v4l2_file_operations helpers */ - -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_device *vdev = video_devdata(file); - - return vb2_mmap(vdev->queue, vma); -} -EXPORT_SYMBOL_GPL(vb2_fop_mmap); - -int _vb2_fop_release(struct file *file, struct mutex *lock) -{ - struct video_device *vdev = video_devdata(file); - - if (lock) - mutex_lock(lock); - if (file->private_data == vdev->queue->owner) { - vb2_queue_release(vdev->queue); - vdev->queue->owner = NULL; - } - if (lock) - mutex_unlock(lock); - return v4l2_fh_release(file); -} -EXPORT_SYMBOL_GPL(_vb2_fop_release); - -int vb2_fop_release(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; - - return _vb2_fop_release(file, lock); -} -EXPORT_SYMBOL_GPL(vb2_fop_release); - -ssize_t vb2_fop_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct video_device *vdev = video_devdata(file); - struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; - int err = -EBUSY; - - if (!(vdev->queue->io_modes & VB2_WRITE)) - return -EINVAL; - if (lock && mutex_lock_interruptible(lock)) - return -ERESTARTSYS; - if (vb2_queue_is_busy(vdev, file)) - goto exit; - err = vb2_write(vdev->queue, buf, count, ppos, - file->f_flags & O_NONBLOCK); - if (vdev->queue->fileio) - vdev->queue->owner = file->private_data; -exit: - if (lock) - mutex_unlock(lock); - return err; -} -EXPORT_SYMBOL_GPL(vb2_fop_write); - -ssize_t vb2_fop_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct video_device *vdev = video_devdata(file); - struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; - int err = -EBUSY; - - if (!(vdev->queue->io_modes & VB2_READ)) - return -EINVAL; - if (lock && mutex_lock_interruptible(lock)) - return -ERESTARTSYS; - if (vb2_queue_is_busy(vdev, file)) - goto exit; - err = vb2_read(vdev->queue, buf, count, ppos, - file->f_flags & O_NONBLOCK); - if (vdev->queue->fileio) - vdev->queue->owner = file->private_data; -exit: - if (lock) - mutex_unlock(lock); - return err; -} -EXPORT_SYMBOL_GPL(vb2_fop_read); - -unsigned int vb2_fop_poll(struct file *file, poll_table *wait) -{ - struct video_device *vdev = video_devdata(file); - struct vb2_queue *q = vdev->queue; - struct mutex *lock = q->lock ? q->lock : vdev->lock; - unsigned res; - void *fileio; - - /* - * If this helper doesn't know how to lock, then you shouldn't be using - * it but you should write your own. - */ - WARN_ON(!lock); - - if (lock && mutex_lock_interruptible(lock)) - return POLLERR; - - fileio = q->fileio; - - res = vb2_poll(vdev->queue, file, wait); - - /* If fileio was started, then we have a new queue owner. */ - if (!fileio && q->fileio) - q->owner = file->private_data; - if (lock) - mutex_unlock(lock); - return res; -} -EXPORT_SYMBOL_GPL(vb2_fop_poll); - -#ifndef CONFIG_MMU -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) -{ - struct video_device *vdev = video_devdata(file); - - return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags); -} -EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area); -#endif - -/* vb2_ops helpers. Only use if vq->lock is non-NULL. */ - -void vb2_ops_wait_prepare(struct vb2_queue *vq) -{ - mutex_unlock(vq->lock); -} -EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare); - -void vb2_ops_wait_finish(struct vb2_queue *vq) -{ - mutex_lock(vq->lock); -} -EXPORT_SYMBOL_GPL(vb2_ops_wait_finish); +EXPORT_SYMBOL_GPL(vb2_core_queue_release); MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2"); MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski"); diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index 2397ceb1dc6b..c33127284cfe 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -17,7 +17,7 @@ #include <linux/slab.h> #include <linux/dma-mapping.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include <media/videobuf2-memops.h> @@ -100,7 +100,8 @@ static void vb2_dc_prepare(void *buf_priv) if (!sgt || buf->db_attach) return; - dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir); + dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->orig_nents, + buf->dma_dir); } static void vb2_dc_finish(void *buf_priv) @@ -112,7 +113,7 @@ static void vb2_dc_finish(void *buf_priv) if (!sgt || buf->db_attach) return; - dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir); + dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir); } /*********************************************/ diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c index be7bd6535c9d..9985c89f0513 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c @@ -17,7 +17,7 @@ #include <linux/slab.h> #include <linux/vmalloc.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-memops.h> #include <media/videobuf2-dma-sg.h> @@ -210,7 +210,8 @@ static void vb2_dma_sg_prepare(void *buf_priv) if (buf->db_attach) return; - dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir); + dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->orig_nents, + buf->dma_dir); } static void vb2_dma_sg_finish(void *buf_priv) @@ -222,7 +223,7 @@ static void vb2_dma_sg_finish(void *buf_priv) if (buf->db_attach) return; - dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir); + dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir); } static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h new file mode 100644 index 000000000000..79018c749282 --- /dev/null +++ b/drivers/media/v4l2-core/videobuf2-internal.h @@ -0,0 +1,161 @@ +#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-memops.c b/drivers/media/v4l2-core/videobuf2-memops.c index 48c6a49c4928..dbec5923fcf0 100644 --- a/drivers/media/v4l2-core/videobuf2-memops.c +++ b/drivers/media/v4l2-core/videobuf2-memops.c @@ -19,7 +19,7 @@ #include <linux/sched.h> #include <linux/file.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-memops.h> /** diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c new file mode 100644 index 000000000000..27b4b9e7c0c2 --- /dev/null +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -0,0 +1,1661 @@ +/* + * videobuf2-v4l2.c - V4L2 driver helper framework + * + * Copyright (C) 2010 Samsung Electronics + * + * Author: Pawel Osciak <pawel@osciak.com> + * Marek Szyprowski <m.szyprowski@samsung.com> + * + * The vb2_thread implementation was based on code from videobuf-dvb.c: + * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs] + * + * 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. + */ + +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/poll.h> +#include <linux/slab.h> +#include <linux/sched.h> +#include <linux/freezer.h> +#include <linux/kthread.h> + +#include <media/v4l2-dev.h> +#include <media/v4l2-fh.h> +#include <media/v4l2-event.h> +#include <media/v4l2-common.h> + +#include <media/videobuf2-v4l2.h> + +#include "videobuf2-internal.h" + +/* Flags that are set by the vb2 core */ +#define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \ + V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \ + V4L2_BUF_FLAG_PREPARED | \ + V4L2_BUF_FLAG_TIMESTAMP_MASK) +/* Output buffer flags that should be passed on to the driver */ +#define V4L2_BUFFER_OUT_FLAGS (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \ + V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE) + +/** + * __verify_planes_array() - verify that the planes array passed in struct + * v4l2_buffer from userspace can be safely used + */ +static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b) +{ + if (!V4L2_TYPE_IS_MULTIPLANAR(b->type)) + return 0; + + /* Is memory for copying plane information present? */ + if (NULL == b->m.planes) { + dprintk(1, "multi-planar buffer passed but " + "planes array not provided\n"); + return -EINVAL; + } + + if (b->length < vb->num_planes || b->length > VB2_MAX_PLANES) { + dprintk(1, "incorrect planes array length, " + "expected %d, got %d\n", vb->num_planes, b->length); + return -EINVAL; + } + + return 0; +} + +/** + * __verify_length() - Verify that the bytesused value for each plane fits in + * the plane length and that the data offset doesn't exceed the bytesused value. + */ +static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) +{ + unsigned int length; + unsigned int bytesused; + unsigned int plane; + + if (!V4L2_TYPE_IS_OUTPUT(b->type)) + return 0; + + if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { + for (plane = 0; plane < vb->num_planes; ++plane) { + length = (b->memory == VB2_MEMORY_USERPTR || + b->memory == VB2_MEMORY_DMABUF) + ? b->m.planes[plane].length + : vb->planes[plane].length; + bytesused = b->m.planes[plane].bytesused + ? b->m.planes[plane].bytesused : length; + + if (b->m.planes[plane].bytesused > length) + return -EINVAL; + + if (b->m.planes[plane].data_offset > 0 && + b->m.planes[plane].data_offset >= bytesused) + return -EINVAL; + } + } else { + length = (b->memory == VB2_MEMORY_USERPTR) + ? b->length : vb->planes[0].length; + + if (b->bytesused > length) + return -EINVAL; + } + + return 0; +} + +static int __set_timestamp(struct vb2_buffer *vb, const void *pb) +{ + const struct v4l2_buffer *b = pb; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct vb2_queue *q = vb->vb2_queue; + + if (q->is_output) { + /* + * 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; + 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) +{ + static bool check_once; + + if (check_once) + return; + + check_once = true; + WARN_ON(1); + + pr_warn("use of bytesused == 0 is deprecated and will be removed in the future,\n"); + if (vb->vb2_queue->allow_zero_bytesused) + pr_warn("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n"); + else + pr_warn("use the actual size instead.\n"); +} + +static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, + const char *opname) +{ + if (b->type != q->type) { + dprintk(1, "%s: invalid buffer type\n", opname); + return -EINVAL; + } + + if (b->index >= q->num_buffers) { + dprintk(1, "%s: buffer index out of range\n", opname); + return -EINVAL; + } + + if (q->bufs[b->index] == NULL) { + /* Should never happen */ + dprintk(1, "%s: buffer is NULL\n", opname); + return -EINVAL; + } + + if (b->memory != q->memory) { + dprintk(1, "%s: invalid memory type\n", opname); + return -EINVAL; + } + + return __verify_planes_array(q->bufs[b->index], b); +} + +/** + * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be + * returned to userspace + */ +static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) +{ + struct v4l2_buffer *b = pb; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct vb2_queue *q = vb->vb2_queue; + unsigned int plane; + + /* Copy back data such as timestamp, flags, etc. */ + b->index = vb->index; + b->type = vb->type; + b->memory = vb->memory; + b->bytesused = 0; + + b->flags = vbuf->flags; + b->field = vbuf->field; + b->timestamp = vbuf->timestamp; + b->timecode = vbuf->timecode; + b->sequence = vbuf->sequence; + b->reserved2 = 0; + b->reserved = 0; + + if (q->is_multiplanar) { + /* + * Fill in plane-related data if userspace provided an array + * for it. The caller has already verified memory and size. + */ + b->length = vb->num_planes; + for (plane = 0; plane < vb->num_planes; ++plane) { + struct v4l2_plane *pdst = &b->m.planes[plane]; + struct vb2_plane *psrc = &vb->planes[plane]; + + pdst->bytesused = psrc->bytesused; + pdst->length = psrc->length; + if (q->memory == VB2_MEMORY_MMAP) + pdst->m.mem_offset = psrc->m.offset; + else if (q->memory == VB2_MEMORY_USERPTR) + pdst->m.userptr = psrc->m.userptr; + else if (q->memory == VB2_MEMORY_DMABUF) + pdst->m.fd = psrc->m.fd; + pdst->data_offset = psrc->data_offset; + memset(pdst->reserved, 0, sizeof(pdst->reserved)); + } + } else { + /* + * We use length and offset in v4l2_planes array even for + * single-planar buffers, but userspace does not. + */ + b->length = vb->planes[0].length; + b->bytesused = vb->planes[0].bytesused; + if (q->memory == VB2_MEMORY_MMAP) + b->m.offset = vb->planes[0].m.offset; + else if (q->memory == VB2_MEMORY_USERPTR) + b->m.userptr = vb->planes[0].m.userptr; + else if (q->memory == VB2_MEMORY_DMABUF) + b->m.fd = vb->planes[0].m.fd; + } + + /* + * Clear any buffer state related flags. + */ + 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) { + /* + * For non-COPY timestamps, drop timestamp source bits + * and obtain the timestamp source from the queue. + */ + b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + } + + switch (vb->state) { + case VB2_BUF_STATE_QUEUED: + case VB2_BUF_STATE_ACTIVE: + b->flags |= V4L2_BUF_FLAG_QUEUED; + break; + case VB2_BUF_STATE_ERROR: + b->flags |= V4L2_BUF_FLAG_ERROR; + /* fall through */ + case VB2_BUF_STATE_DONE: + b->flags |= V4L2_BUF_FLAG_DONE; + break; + case VB2_BUF_STATE_PREPARED: + b->flags |= V4L2_BUF_FLAG_PREPARED; + break; + case VB2_BUF_STATE_PREPARING: + case VB2_BUF_STATE_DEQUEUED: + case VB2_BUF_STATE_REQUEUEING: + /* nothing */ + break; + } + + if (vb2_buffer_in_use(q, vb)) + b->flags |= V4L2_BUF_FLAG_MAPPED; + + return 0; +} + +/** + * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a + * v4l2_buffer by the userspace. It also verifies that struct + * v4l2_buffer has a valid number of planes. + */ +static int __fill_vb2_buffer(struct vb2_buffer *vb, + const void *pb, struct vb2_plane *planes) +{ + struct vb2_queue *q = vb->vb2_queue; + const struct v4l2_buffer *b = pb; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + unsigned int plane; + int ret; + + ret = __verify_length(vb, b); + if (ret < 0) { + dprintk(1, "plane parameters verification failed: %d\n", ret); + return ret; + } + if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) { + /* + * If the format's field is ALTERNATE, then the buffer's field + * should be either TOP or BOTTOM, not ALTERNATE since that + * makes no sense. The driver has to know whether the + * buffer represents a top or a bottom field in order to + * program any DMA correctly. Using ALTERNATE is wrong, since + * that just says that it is either a top or a bottom field, + * but not which of the two it is. + */ + dprintk(1, "the field is incorrectly set to ALTERNATE " + "for an output buffer\n"); + return -EINVAL; + } + vbuf->timestamp.tv_sec = 0; + vbuf->timestamp.tv_usec = 0; + vbuf->sequence = 0; + + if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { + if (b->memory == VB2_MEMORY_USERPTR) { + for (plane = 0; plane < vb->num_planes; ++plane) { + planes[plane].m.userptr = + b->m.planes[plane].m.userptr; + planes[plane].length = + b->m.planes[plane].length; + } + } + if (b->memory == VB2_MEMORY_DMABUF) { + for (plane = 0; plane < vb->num_planes; ++plane) { + planes[plane].m.fd = + b->m.planes[plane].m.fd; + planes[plane].length = + b->m.planes[plane].length; + } + } + + /* Fill in driver-provided information for OUTPUT types */ + if (V4L2_TYPE_IS_OUTPUT(b->type)) { + /* + * Will have to go up to b->length when API starts + * accepting variable number of planes. + * + * If bytesused == 0 for the output buffer, then fall + * back to the full buffer size. In that case + * userspace clearly never bothered to set it and + * it's a safe assumption that they really meant to + * use the full plane sizes. + * + * Some drivers, e.g. old codec drivers, use bytesused == 0 + * as a way to indicate that streaming is finished. + * In that case, the driver should use the + * allow_zero_bytesused flag to keep old userspace + * applications working. + */ + for (plane = 0; plane < vb->num_planes; ++plane) { + struct vb2_plane *pdst = &planes[plane]; + struct v4l2_plane *psrc = &b->m.planes[plane]; + + if (psrc->bytesused == 0) + vb2_warn_zero_bytesused(vb); + + if (vb->vb2_queue->allow_zero_bytesused) + pdst->bytesused = psrc->bytesused; + else + pdst->bytesused = psrc->bytesused ? + psrc->bytesused : pdst->length; + pdst->data_offset = psrc->data_offset; + } + } + } else { + /* + * Single-planar buffers do not use planes array, + * so fill in relevant v4l2_buffer struct fields instead. + * In videobuf we use our internal V4l2_planes struct for + * single-planar buffers as well, for simplicity. + * + * If bytesused == 0 for the output buffer, then fall back + * to the full buffer size as that's a sensible default. + * + * Some drivers, e.g. old codec drivers, use bytesused == 0 as + * a way to indicate that streaming is finished. In that case, + * the driver should use the allow_zero_bytesused flag to keep + * old userspace applications working. + */ + if (b->memory == VB2_MEMORY_USERPTR) { + planes[0].m.userptr = b->m.userptr; + planes[0].length = b->length; + } + + if (b->memory == VB2_MEMORY_DMABUF) { + planes[0].m.fd = b->m.fd; + planes[0].length = b->length; + } + + if (V4L2_TYPE_IS_OUTPUT(b->type)) { + if (b->bytesused == 0) + vb2_warn_zero_bytesused(vb); + + if (vb->vb2_queue->allow_zero_bytesused) + planes[0].bytesused = b->bytesused; + else + planes[0].bytesused = b->bytesused ? + b->bytesused : planes[0].length; + } else + planes[0].bytesused = 0; + + } + + /* 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)) { + /* + * Non-COPY timestamps and non-OUTPUT queues will get + * their timestamp and timestamp source flags from the + * queue. + */ + vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + } + + if (V4L2_TYPE_IS_OUTPUT(b->type)) { + /* + * For output buffers mask out the timecode flag: + * this will be handled later in vb2_internal_qbuf(). + * The 'field' is valid metadata for this output buffer + * and so that needs to be copied here. + */ + vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE; + vbuf->field = b->field; + } else { + /* Zero any output buffer flags as this is a capture buffer */ + vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS; + } + + return 0; +} + +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, +}; + +/** + * vb2_querybuf() - query video buffer information + * @q: videobuf queue + * @b: buffer struct passed from userspace to vidioc_querybuf handler + * in driver + * + * Should be called from vidioc_querybuf ioctl handler in driver. + * This function will verify the passed v4l2_buffer structure and fill 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_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) +{ + struct vb2_buffer *vb; + int ret; + + if (b->type != q->type) { + dprintk(1, "wrong buffer type\n"); + return -EINVAL; + } + + if (b->index >= q->num_buffers) { + dprintk(1, "buffer index out of range\n"); + return -EINVAL; + } + vb = q->bufs[b->index]; + ret = __verify_planes_array(vb, b); + + return ret ? ret : vb2_core_querybuf(q, b->index, b); +} +EXPORT_SYMBOL(vb2_querybuf); + +/** + * vb2_reqbufs() - Wrapper for vb2_core_reqbufs() that also verifies + * the memory and type values. + * @q: videobuf2 queue + * @req: struct passed from userspace to vidioc_reqbufs handler + * in driver + */ +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) +{ + int ret = vb2_verify_memory_type(q, req->memory, req->type); + + return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count); +} +EXPORT_SYMBOL_GPL(vb2_reqbufs); + +/** + * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel + * @q: videobuf2 queue + * @b: buffer structure passed from userspace to vidioc_prepare_buf + * handler in driver + * + * Should be called from vidioc_prepare_buf ioctl handler of a driver. + * This function: + * 1) verifies the passed buffer, + * 2) calls buf_prepare callback in the driver (if provided), in which + * driver-specific buffer initialization can be performed, + * + * The return values from this function are intended to be directly returned + * from vidioc_prepare_buf handler in driver. + */ +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b) +{ + int ret; + + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); + return -EBUSY; + } + + ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf"); + + return ret ? ret : vb2_core_prepare_buf(q, b->index, b); +} +EXPORT_SYMBOL_GPL(vb2_prepare_buf); + +/** + * vb2_create_bufs() - Wrapper for vb2_core_create_bufs() that also verifies + * the memory and type values. + * @q: videobuf2 queue + * @create: creation parameters, passed from userspace to vidioc_create_bufs + * handler in driver + */ +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); + + create->index = q->num_buffers; + if (create->count == 0) + return ret != -EBUSY ? ret : 0; + return ret ? ret : vb2_core_create_bufs(q, create->memory, + &create->count, &create->format); +} +EXPORT_SYMBOL_GPL(vb2_create_bufs); + +static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) +{ + int ret = vb2_queue_or_prepare_buf(q, b, "qbuf"); + + return ret ? ret : vb2_core_qbuf(q, b->index, b); +} + +/** + * vb2_qbuf() - Queue a buffer from userspace + * @q: videobuf2 queue + * @b: buffer structure passed from userspace to vidioc_qbuf handler + * in driver + * + * Should be called from vidioc_qbuf ioctl handler of a driver. + * This function: + * 1) verifies the passed buffer, + * 2) if necessary, calls buf_prepare callback in the driver (if provided), in + * which driver-specific buffer initialization can be performed, + * 3) if streaming is on, queues the buffer in driver by the means of buf_queue + * callback for processing. + * + * The return values from this function are intended to be directly returned + * from vidioc_qbuf handler in driver. + */ +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) +{ + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); + return -EBUSY; + } + + return vb2_internal_qbuf(q, b); +} +EXPORT_SYMBOL_GPL(vb2_qbuf); + +static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, + bool nonblocking) +{ + int ret; + + if (b->type != q->type) { + dprintk(1, "invalid buffer type\n"); + return -EINVAL; + } + + 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; +} + +/** + * vb2_dqbuf() - Dequeue a buffer to the userspace + * @q: videobuf2 queue + * @b: buffer structure passed from userspace to vidioc_dqbuf handler + * in driver + * @nonblocking: if true, this call will not sleep waiting for a buffer if no + * buffers ready for dequeuing are present. Normally the driver + * would be passing (file->f_flags & O_NONBLOCK) here + * + * Should be called from vidioc_dqbuf ioctl handler of a driver. + * This function: + * 1) verifies the passed buffer, + * 2) calls buf_finish callback in the driver (if provided), in which + * driver can perform any additional operations that may be required before + * returning the buffer to userspace, such as cache sync, + * 3) the buffer struct members are filled with relevant information for + * the userspace. + * + * The return values from this function are intended to be directly returned + * from vidioc_dqbuf handler in driver. + */ +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) +{ + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); + return -EBUSY; + } + return vb2_internal_dqbuf(q, b, nonblocking); +} +EXPORT_SYMBOL_GPL(vb2_dqbuf); + +/** + * vb2_streamon - start streaming + * @q: videobuf2 queue + * @type: type argument passed from userspace to vidioc_streamon handler + * + * Should be called from vidioc_streamon handler of a driver. + * This function: + * 1) verifies current state + * 2) passes any previously queued buffers to the driver and starts streaming + * + * The return values from this function are intended to be directly returned + * from vidioc_streamon handler in the driver. + */ +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type) +{ + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); + return -EBUSY; + } + return vb2_core_streamon(q, type); +} +EXPORT_SYMBOL_GPL(vb2_streamon); + +/** + * vb2_streamoff - stop streaming + * @q: videobuf2 queue + * @type: type argument passed from userspace to vidioc_streamoff handler + * + * Should be called from vidioc_streamoff handler of a driver. + * This function: + * 1) verifies current state, + * 2) stop streaming and dequeues any queued buffers, including those previously + * passed to the driver (after waiting for the driver to finish). + * + * This call can be used for pausing playback. + * The return values from this function are intended to be directly returned + * from vidioc_streamoff handler in the driver + */ +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) +{ + if (vb2_fileio_is_active(q)) { + dprintk(1, "file io in progress\n"); + return -EBUSY; + } + return vb2_core_streamoff(q, type); +} +EXPORT_SYMBOL_GPL(vb2_streamoff); + +/** + * vb2_expbuf() - Export a buffer as a file descriptor + * @q: videobuf2 queue + * @eb: export buffer structure passed from userspace to vidioc_expbuf + * handler in driver + * + * The return values from this function are intended to be directly returned + * from vidioc_expbuf handler in driver. + */ +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) +{ + return vb2_core_expbuf(q, &eb->fd, eb->type, eb->index, + eb->plane, eb->flags); +} +EXPORT_SYMBOL_GPL(vb2_expbuf); + +/** + * vb2_queue_init() - initialize a videobuf2 queue + * @q: videobuf2 queue; this structure should be allocated in driver + * + * The vb2_queue structure should be allocated by the driver. The driver is + * responsible of clearing it's content and setting initial values for some + * required entries before calling this function. + * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer + * to the struct vb2_queue description in include/media/videobuf2-core.h + * for more information. + */ +int vb2_queue_init(struct vb2_queue *q) +{ + /* + * Sanity check + */ + if (WARN_ON(!q) || + WARN_ON(q->timestamp_flags & + ~(V4L2_BUF_FLAG_TIMESTAMP_MASK | + V4L2_BUF_FLAG_TSTAMP_SRC_MASK))) + return -EINVAL; + + /* Warn that the driver should choose an appropriate timestamp type */ + WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == + V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN); + + /* Warn that vb2_memory should match with v4l2_memory */ + if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP) + || WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR) + || WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF)) + return -EINVAL; + + if (q->buf_struct_size == 0) + q->buf_struct_size = sizeof(struct vb2_v4l2_buffer); + + q->buf_ops = &v4l2_buf_ops; + q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type); + q->is_output = V4L2_TYPE_IS_OUTPUT(q->type); + + 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 + * + * This function stops streaming and performs necessary clean ups, including + * freeing video buffer memory. The driver is responsible for freeing + * the vb2_queue structure itself. + */ +void vb2_queue_release(struct vb2_queue *q) +{ + __vb2_cleanup_fileio(q); + vb2_core_queue_release(q); +} +EXPORT_SYMBOL_GPL(vb2_queue_release); + +/** + * vb2_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. + * + * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any + * pending events. + * + * The return values from this function are intended to be directly returned + * from poll handler in driver. + */ +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; + + if (v4l2_event_pending(fh)) + res = POLLPRI; + else if (req_events & POLLPRI) + 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); + } + + /* + * 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; +} +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 + * and struct vb2_ops. + * They contain boilerplate code that most if not all drivers have to do + * and so they simplify the driver code. + */ + +/* The queue is busy if there is a owner and you are not that owner. */ +static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file) +{ + return vdev->queue->owner && vdev->queue->owner != file->private_data; +} + +/* vb2 ioctl helpers */ + +int vb2_ioctl_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) +{ + struct video_device *vdev = video_devdata(file); + int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type); + + if (res) + return res; + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count); + /* If count == 0, then the owner has released all buffers and he + is no longer owner of the queue. Otherwise we have a new owner. */ + if (res == 0) + vdev->queue->owner = p->count ? file->private_data : NULL; + return res; +} +EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs); + +int vb2_ioctl_create_bufs(struct file *file, void *priv, + struct v4l2_create_buffers *p) +{ + struct video_device *vdev = video_devdata(file); + int res = vb2_verify_memory_type(vdev->queue, p->memory, + p->format.type); + + p->index = vdev->queue->num_buffers; + /* + * If count == 0, then just check if memory and type are valid. + * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. + */ + if (p->count == 0) + return res != -EBUSY ? res : 0; + if (res) + return res; + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + res = vb2_core_create_bufs(vdev->queue, p->memory, &p->count, + &p->format); + if (res == 0) + vdev->queue->owner = file->private_data; + return res; +} +EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs); + +int vb2_ioctl_prepare_buf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_prepare_buf(vdev->queue, p); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf); + +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct video_device *vdev = video_devdata(file); + + /* No need to call vb2_queue_is_busy(), anyone can query buffers. */ + return vb2_querybuf(vdev->queue, p); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf); + +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_qbuf(vdev->queue, p); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf); + +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf); + +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_streamon(vdev->queue, i); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_streamon); + +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_streamoff(vdev->queue, i); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff); + +int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p) +{ + struct video_device *vdev = video_devdata(file); + + if (vb2_queue_is_busy(vdev, file)) + return -EBUSY; + return vb2_expbuf(vdev->queue, p); +} +EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf); + +/* v4l2_file_operations helpers */ + +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_device *vdev = video_devdata(file); + + return vb2_mmap(vdev->queue, vma); +} +EXPORT_SYMBOL_GPL(vb2_fop_mmap); + +int _vb2_fop_release(struct file *file, struct mutex *lock) +{ + struct video_device *vdev = video_devdata(file); + + if (lock) + mutex_lock(lock); + if (file->private_data == vdev->queue->owner) { + vb2_queue_release(vdev->queue); + vdev->queue->owner = NULL; + } + if (lock) + mutex_unlock(lock); + return v4l2_fh_release(file); +} +EXPORT_SYMBOL_GPL(_vb2_fop_release); + +int vb2_fop_release(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; + + return _vb2_fop_release(file, lock); +} +EXPORT_SYMBOL_GPL(vb2_fop_release); + +ssize_t vb2_fop_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct video_device *vdev = video_devdata(file); + struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; + int err = -EBUSY; + + if (!(vdev->queue->io_modes & VB2_WRITE)) + return -EINVAL; + if (lock && mutex_lock_interruptible(lock)) + return -ERESTARTSYS; + if (vb2_queue_is_busy(vdev, file)) + goto exit; + err = vb2_write(vdev->queue, buf, count, ppos, + file->f_flags & O_NONBLOCK); + if (vdev->queue->fileio) + vdev->queue->owner = file->private_data; +exit: + if (lock) + mutex_unlock(lock); + return err; +} +EXPORT_SYMBOL_GPL(vb2_fop_write); + +ssize_t vb2_fop_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct video_device *vdev = video_devdata(file); + struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; + int err = -EBUSY; + + if (!(vdev->queue->io_modes & VB2_READ)) + return -EINVAL; + if (lock && mutex_lock_interruptible(lock)) + return -ERESTARTSYS; + if (vb2_queue_is_busy(vdev, file)) + goto exit; + err = vb2_read(vdev->queue, buf, count, ppos, + file->f_flags & O_NONBLOCK); + if (vdev->queue->fileio) + vdev->queue->owner = file->private_data; +exit: + if (lock) + mutex_unlock(lock); + return err; +} +EXPORT_SYMBOL_GPL(vb2_fop_read); + +unsigned int vb2_fop_poll(struct file *file, poll_table *wait) +{ + struct video_device *vdev = video_devdata(file); + struct vb2_queue *q = vdev->queue; + struct mutex *lock = q->lock ? q->lock : vdev->lock; + unsigned res; + void *fileio; + + /* + * If this helper doesn't know how to lock, then you shouldn't be using + * it but you should write your own. + */ + WARN_ON(!lock); + + if (lock && mutex_lock_interruptible(lock)) + return POLLERR; + + fileio = q->fileio; + + res = vb2_poll(vdev->queue, file, wait); + + /* If fileio was started, then we have a new queue owner. */ + if (!fileio && q->fileio) + q->owner = file->private_data; + if (lock) + mutex_unlock(lock); + return res; +} +EXPORT_SYMBOL_GPL(vb2_fop_poll); + +#ifndef CONFIG_MMU +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct video_device *vdev = video_devdata(file); + + return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags); +} +EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area); +#endif + +/* vb2_ops helpers. Only use if vq->lock is non-NULL. */ + +void vb2_ops_wait_prepare(struct vb2_queue *vq) +{ + mutex_unlock(vq->lock); +} +EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare); + +void vb2_ops_wait_finish(struct vb2_queue *vq) +{ + mutex_lock(vq->lock); +} +EXPORT_SYMBOL_GPL(vb2_ops_wait_finish); + +MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2"); +MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c index ecb8f0c7f025..1c302743a1fd 100644 --- a/drivers/media/v4l2-core/videobuf2-vmalloc.c +++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c @@ -17,7 +17,7 @@ #include <linux/slab.h> #include <linux/vmalloc.h> -#include <media/videobuf2-core.h> +#include <media/videobuf2-v4l2.h> #include <media/videobuf2-vmalloc.h> #include <media/videobuf2-memops.h> |