summaryrefslogtreecommitdiff
path: root/drivers/media/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/Kconfig2
-rw-r--r--drivers/media/video/cx18/cx18-streams.c10
-rw-r--r--drivers/media/video/cx23885/Kconfig1
-rw-r--r--drivers/media/video/cx88/cx88-input.c2
-rw-r--r--drivers/media/video/imx074.c2
-rw-r--r--drivers/media/video/m52790.c2
-rw-r--r--drivers/media/video/omap3isp/isp.c34
-rw-r--r--drivers/media/video/omap3isp/isp.h12
-rw-r--r--drivers/media/video/omap3isp/ispccdc.c37
-rw-r--r--drivers/media/video/omap3isp/isppreview.c2
-rw-r--r--drivers/media/video/omap3isp/ispqueue.c6
-rw-r--r--drivers/media/video/omap3isp/ispresizer.c75
-rw-r--r--drivers/media/video/omap3isp/ispstat.h6
-rw-r--r--drivers/media/video/omap3isp/ispvideo.c108
-rw-r--r--drivers/media/video/omap3isp/ispvideo.h3
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c8
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c74
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c10
-rw-r--r--drivers/media/video/sh_mobile_csi2.c11
-rw-r--r--drivers/media/video/soc_camera.c55
-rw-r--r--drivers/media/video/tda9840.c2
-rw-r--r--drivers/media/video/tea6415c.c2
-rw-r--r--drivers/media/video/tea6420.c2
-rw-r--r--drivers/media/video/upd64031a.c2
-rw-r--r--drivers/media/video/upd64083.c2
-rw-r--r--drivers/media/video/v4l2-dev.c15
-rw-r--r--drivers/media/video/v4l2-device.c5
-rw-r--r--drivers/media/video/v4l2-subdev.c14
-rw-r--r--drivers/media/video/videobuf-dma-contig.c2
-rw-r--r--drivers/media/video/videobuf2-core.c17
-rw-r--r--drivers/media/video/videobuf2-dma-contig.c2
31 files changed, 392 insertions, 133 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 4498b944dec8..00f51dd121f3 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -875,7 +875,7 @@ config MX3_VIDEO
config VIDEO_MX3
tristate "i.MX3x Camera Sensor Interface driver"
depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
- select VIDEOBUF_DMA_CONTIG
+ select VIDEOBUF2_DMA_CONTIG
select MX3_VIDEO
---help---
This is a v4l2 driver for the i.MX3x Camera Sensor Interface
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index c6e2ca3b1149..6fbc356113c1 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -350,9 +350,17 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
/* No struct video_device, but can have buffers allocated */
if (type == CX18_ENC_STREAM_TYPE_IDX) {
+ /* If the module params didn't inhibit IDX ... */
if (cx->stream_buffers[type] != 0) {
cx->stream_buffers[type] = 0;
- cx18_stream_free(&cx->streams[type]);
+ /*
+ * Before calling cx18_stream_free(),
+ * check if the IDX stream was actually set up.
+ * Needed, since the cx18_probe() error path
+ * exits through here as well as normal clean up
+ */
+ if (cx->streams[type].buffers != 0)
+ cx18_stream_free(&cx->streams[type]);
}
continue;
}
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index 3b6e7f28568e..caab1bfb79e2 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -22,6 +22,7 @@ config VIDEO_CX23885
select DVB_CX24116 if !DVB_FE_CUSTOMISE
select DVB_STV0900 if !DVB_FE_CUSTOMISE
select DVB_DS3000 if !DVB_FE_CUSTOMISE
+ select DVB_STV0367 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index c820e2f53527..3f442003623d 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -524,7 +524,7 @@ void cx88_ir_irq(struct cx88_core *core)
for (todo = 32; todo > 0; todo -= bits) {
ev.pulse = samples & 0x80000000 ? false : true;
bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
- ev.duration = (bits * NSEC_PER_SEC) / (1000 * ir_samplerate);
+ ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;
ir_raw_event_store_with_filter(ir->dev, &ev);
samples <<= bits;
}
diff --git a/drivers/media/video/imx074.c b/drivers/media/video/imx074.c
index 1a1169115716..0382ea752e6f 100644
--- a/drivers/media/video/imx074.c
+++ b/drivers/media/video/imx074.c
@@ -298,7 +298,7 @@ static unsigned long imx074_query_bus_param(struct soc_camera_device *icd)
static int imx074_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
- return -1;
+ return -EINVAL;
}
static struct soc_camera_ops imx074_ops = {
diff --git a/drivers/media/video/m52790.c b/drivers/media/video/m52790.c
index 5e1c9a81984c..303ffa7df4ac 100644
--- a/drivers/media/video/m52790.c
+++ b/drivers/media/video/m52790.c
@@ -174,7 +174,7 @@ static int m52790_probe(struct i2c_client *client,
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
- state = kmalloc(sizeof(struct m52790_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct m52790_state), GFP_KERNEL);
if (state == NULL)
return -ENOMEM;
diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c
index 503bd7922bd6..472a69359e60 100644
--- a/drivers/media/video/omap3isp/isp.c
+++ b/drivers/media/video/omap3isp/isp.c
@@ -215,20 +215,21 @@ static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
}
switch (xclksel) {
- case 0:
+ case ISP_XCLK_A:
isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
ISPTCTRL_CTRL_DIVA_MASK,
divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
dev_dbg(isp->dev, "isp_set_xclk(): cam_xclka set to %d Hz\n",
currentxclk);
break;
- case 1:
+ case ISP_XCLK_B:
isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
ISPTCTRL_CTRL_DIVB_MASK,
divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
dev_dbg(isp->dev, "isp_set_xclk(): cam_xclkb set to %d Hz\n",
currentxclk);
break;
+ case ISP_XCLK_NONE:
default:
omap3isp_put(isp);
dev_dbg(isp->dev, "ISP_ERR: isp_set_xclk(): Invalid requested "
@@ -237,13 +238,13 @@ static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
}
/* Do we go from stable whatever to clock? */
- if (divisor >= 2 && isp->xclk_divisor[xclksel] < 2)
+ if (divisor >= 2 && isp->xclk_divisor[xclksel - 1] < 2)
omap3isp_get(isp);
/* Stopping the clock. */
- else if (divisor < 2 && isp->xclk_divisor[xclksel] >= 2)
+ else if (divisor < 2 && isp->xclk_divisor[xclksel - 1] >= 2)
omap3isp_put(isp);
- isp->xclk_divisor[xclksel] = divisor;
+ isp->xclk_divisor[xclksel - 1] = divisor;
omap3isp_put(isp);
@@ -285,7 +286,8 @@ static void isp_power_settings(struct isp_device *isp, int idle)
*/
void omap3isp_configure_bridge(struct isp_device *isp,
enum ccdc_input_entity input,
- const struct isp_parallel_platform_data *pdata)
+ const struct isp_parallel_platform_data *pdata,
+ unsigned int shift)
{
u32 ispctrl_val;
@@ -298,9 +300,9 @@ void omap3isp_configure_bridge(struct isp_device *isp,
switch (input) {
case CCDC_INPUT_PARALLEL:
ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
- ispctrl_val |= pdata->data_lane_shift << ISPCTRL_SHIFT_SHIFT;
ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
ispctrl_val |= pdata->bridge << ISPCTRL_PAR_BRIDGE_SHIFT;
+ shift += pdata->data_lane_shift * 2;
break;
case CCDC_INPUT_CSI2A:
@@ -319,6 +321,8 @@ void omap3isp_configure_bridge(struct isp_device *isp,
return;
}
+ ispctrl_val |= ((shift/2) << ISPCTRL_SHIFT_SHIFT) & ISPCTRL_SHIFT_MASK;
+
ispctrl_val &= ~ISPCTRL_SYNC_DETECT_MASK;
ispctrl_val |= ISPCTRL_SYNC_DETECT_VSRISE;
@@ -658,6 +662,8 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
/* Apply power change to connected non-nodes. */
ret = isp_pipeline_pm_power(entity, change);
+ if (ret < 0)
+ entity->use_count -= change;
mutex_unlock(&entity->parent->graph_mutex);
@@ -872,6 +878,9 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
}
}
+ if (failure < 0)
+ isp->needs_reset = true;
+
return failure;
}
@@ -884,7 +893,8 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
* single-shot or continuous mode.
*
* Return 0 if successful, or the return value of the failed video::s_stream
- * operation otherwise.
+ * operation otherwise. The pipeline state is not updated when the operation
+ * fails, except when stopping the pipeline.
*/
int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
enum isp_pipeline_stream_state state)
@@ -895,7 +905,9 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
ret = isp_pipeline_disable(pipe);
else
ret = isp_pipeline_enable(pipe, state);
- pipe->stream_state = state;
+
+ if (ret == 0 || state == ISP_PIPELINE_STREAM_STOPPED)
+ pipe->stream_state = state;
return ret;
}
@@ -1481,6 +1493,10 @@ void omap3isp_put(struct isp_device *isp)
if (--isp->ref_count == 0) {
isp_disable_interrupts(isp);
isp_save_ctx(isp);
+ if (isp->needs_reset) {
+ isp_reset(isp);
+ isp->needs_reset = false;
+ }
isp_disable_clocks(isp);
}
mutex_unlock(&isp->isp_mutex);
diff --git a/drivers/media/video/omap3isp/isp.h b/drivers/media/video/omap3isp/isp.h
index cf5214e95a92..2620c405f5e4 100644
--- a/drivers/media/video/omap3isp/isp.h
+++ b/drivers/media/video/omap3isp/isp.h
@@ -132,7 +132,6 @@ struct isp_reg {
/**
* struct isp_parallel_platform_data - Parallel interface platform data
- * @width: Parallel bus width in bits (8, 10, 11 or 12)
* @data_lane_shift: Data lane shifter
* 0 - CAMEXT[13:0] -> CAM[13:0]
* 1 - CAMEXT[13:2] -> CAM[11:0]
@@ -146,7 +145,6 @@ struct isp_reg {
* ISPCTRL_PAR_BRIDGE_BENDIAN - Big endian
*/
struct isp_parallel_platform_data {
- unsigned int width;
unsigned int data_lane_shift:2;
unsigned int clk_pol:1;
unsigned int bridge:4;
@@ -262,6 +260,7 @@ struct isp_device {
/* ISP Obj */
spinlock_t stat_lock; /* common lock for statistic drivers */
struct mutex isp_mutex; /* For handling ref_count field */
+ bool needs_reset;
int has_context;
int ref_count;
unsigned int autoidle;
@@ -311,11 +310,12 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
enum isp_pipeline_stream_state state);
void omap3isp_configure_bridge(struct isp_device *isp,
enum ccdc_input_entity input,
- const struct isp_parallel_platform_data *pdata);
+ const struct isp_parallel_platform_data *pdata,
+ unsigned int shift);
-#define ISP_XCLK_NONE -1
-#define ISP_XCLK_A 0
-#define ISP_XCLK_B 1
+#define ISP_XCLK_NONE 0
+#define ISP_XCLK_A 1
+#define ISP_XCLK_B 2
struct isp_device *omap3isp_get(struct isp_device *isp);
void omap3isp_put(struct isp_device *isp);
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index 5ff9d14ce710..39d501bda636 100644
--- a/drivers/media/video/omap3isp/ispccdc.c
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -43,6 +43,12 @@ __ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
static const unsigned int ccdc_fmts[] = {
V4L2_MBUS_FMT_Y8_1X8,
+ V4L2_MBUS_FMT_Y10_1X10,
+ V4L2_MBUS_FMT_Y12_1X12,
+ V4L2_MBUS_FMT_SGRBG8_1X8,
+ V4L2_MBUS_FMT_SRGGB8_1X8,
+ V4L2_MBUS_FMT_SBGGR8_1X8,
+ V4L2_MBUS_FMT_SGBRG8_1X8,
V4L2_MBUS_FMT_SGRBG10_1X10,
V4L2_MBUS_FMT_SRGGB10_1X10,
V4L2_MBUS_FMT_SBGGR10_1X10,
@@ -1110,21 +1116,38 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
struct isp_parallel_platform_data *pdata = NULL;
struct v4l2_subdev *sensor;
struct v4l2_mbus_framefmt *format;
+ const struct isp_format_info *fmt_info;
+ struct v4l2_subdev_format fmt_src;
+ unsigned int depth_out;
+ unsigned int depth_in = 0;
struct media_pad *pad;
unsigned long flags;
+ unsigned int shift;
u32 syn_mode;
u32 ccdc_pattern;
- if (ccdc->input == CCDC_INPUT_PARALLEL) {
- pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
- sensor = media_entity_to_v4l2_subdev(pad->entity);
+ pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
+ sensor = media_entity_to_v4l2_subdev(pad->entity);
+ if (ccdc->input == CCDC_INPUT_PARALLEL)
pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
->bus.parallel;
+
+ /* Compute shift value for lane shifter to configure the bridge. */
+ fmt_src.pad = pad->index;
+ fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) {
+ fmt_info = omap3isp_video_format_info(fmt_src.format.code);
+ depth_in = fmt_info->bpp;
}
- omap3isp_configure_bridge(isp, ccdc->input, pdata);
+ fmt_info = omap3isp_video_format_info
+ (isp->isp_ccdc.formats[CCDC_PAD_SINK].code);
+ depth_out = fmt_info->bpp;
+
+ shift = depth_in - depth_out;
+ omap3isp_configure_bridge(isp, ccdc->input, pdata, shift);
- ccdc->syncif.datsz = pdata ? pdata->width : 10;
+ ccdc->syncif.datsz = depth_out;
ccdc_config_sync_if(ccdc, &ccdc->syncif);
/* CCDC_PAD_SINK */
@@ -1338,7 +1361,7 @@ static int ccdc_sbl_wait_idle(struct isp_ccdc_device *ccdc,
* @ccdc: Pointer to ISP CCDC device.
* @event: Pointing which event trigger handler
*
- * Return 1 when the event and stopping request combination is satisfyied,
+ * Return 1 when the event and stopping request combination is satisfied,
* zero otherwise.
*/
static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
@@ -1618,7 +1641,7 @@ static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
ccdc_set_outaddr(ccdc, buffer->isp_addr);
- /* We now have a buffer queued on the output, restart the pipeline in
+ /* We now have a buffer queued on the output, restart the pipeline
* on the next CCDC interrupt if running in continuous mode (or when
* starting the stream).
*/
diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c
index 2b16988a501d..aba537af87e4 100644
--- a/drivers/media/video/omap3isp/isppreview.c
+++ b/drivers/media/video/omap3isp/isppreview.c
@@ -755,7 +755,7 @@ static struct preview_update update_attrs[] = {
* @configs - pointer to update config structure.
* @config - return pointer to appropriate structure field.
* @bit - for which feature to return pointers.
- * Return size of coresponding prev_params member
+ * Return size of corresponding prev_params member
*/
static u32
__preview_get_ptrs(struct prev_params *params, void **param,
diff --git a/drivers/media/video/omap3isp/ispqueue.c b/drivers/media/video/omap3isp/ispqueue.c
index 8fddc5806b0d..9c317148205f 100644
--- a/drivers/media/video/omap3isp/ispqueue.c
+++ b/drivers/media/video/omap3isp/ispqueue.c
@@ -339,7 +339,7 @@ static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
up_read(&current->mm->mmap_sem);
if (ret != buf->npages) {
- buf->npages = ret;
+ buf->npages = ret < 0 ? 0 : ret;
isp_video_buffer_cleanup(buf);
return -EFAULT;
}
@@ -408,8 +408,8 @@ done:
* isp_video_buffer_prepare_vm_flags - Get VMA flags for a userspace address
*
* This function locates the VMAs for the buffer's userspace address and checks
- * that their flags match. The onlflag that we need to care for at the moment is
- * VM_PFNMAP.
+ * that their flags match. The only flag that we need to care for at the moment
+ * is VM_PFNMAP.
*
* The buffer vm_flags field is set to the first VMA flags.
*
diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/video/omap3isp/ispresizer.c
index 653f88ba56db..0bb0f8cd36f5 100644
--- a/drivers/media/video/omap3isp/ispresizer.c
+++ b/drivers/media/video/omap3isp/ispresizer.c
@@ -714,19 +714,50 @@ static void resizer_print_status(struct isp_res_device *res)
* iw and ih are the input width and height after cropping. Those equations need
* to be satisfied exactly for the resizer to work correctly.
*
- * Reverting the equations, we can compute the resizing ratios with
+ * The equations can't be easily reverted, as the >> 8 operation is not linear.
+ * In addition, not all input sizes can be achieved for a given output size. To
+ * get the highest input size lower than or equal to the requested input size,
+ * we need to compute the highest resizing ratio that satisfies the following
+ * inequality (taking the 4-tap mode width equation as an example)
+ *
+ * iw >= (32 * sph + (ow - 1) * hrsz + 16) >> 8 - 7
+ *
+ * (where iw is the requested input width) which can be rewritten as
+ *
+ * iw - 7 >= (32 * sph + (ow - 1) * hrsz + 16) >> 8
+ * (iw - 7) << 8 >= 32 * sph + (ow - 1) * hrsz + 16 - b
+ * ((iw - 7) << 8) + b >= 32 * sph + (ow - 1) * hrsz + 16
+ *
+ * where b is the value of the 8 least significant bits of the right hand side
+ * expression of the last inequality. The highest resizing ratio value will be
+ * achieved when b is equal to its maximum value of 255. That resizing ratio
+ * value will still satisfy the original inequality, as b will disappear when
+ * the expression will be shifted right by 8.
+ *
+ * The reverted the equations thus become
*
* - 8-phase, 4-tap mode
- * hrsz = ((iw - 7) * 256 - 16 - 32 * sph) / (ow - 1)
- * vrsz = ((ih - 4) * 256 - 16 - 32 * spv) / (oh - 1)
+ * hrsz = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / (ow - 1)
+ * vrsz = ((ih - 4) * 256 + 255 - 16 - 32 * spv) / (oh - 1)
* - 4-phase, 7-tap mode
- * hrsz = ((iw - 7) * 256 - 32 - 64 * sph) / (ow - 1)
- * vrsz = ((ih - 7) * 256 - 32 - 64 * spv) / (oh - 1)
+ * hrsz = ((iw - 7) * 256 + 255 - 32 - 64 * sph) / (ow - 1)
+ * vrsz = ((ih - 7) * 256 + 255 - 32 - 64 * spv) / (oh - 1)
*
- * The ratios are integer values, and must be rounded down to ensure that the
- * cropped input size is not bigger than the uncropped input size. As the ratio
- * in 7-tap mode is always smaller than the ratio in 4-tap mode, we can use the
- * 7-tap mode equations to compute a ratio approximation.
+ * The ratios are integer values, and are rounded down to ensure that the
+ * cropped input size is not bigger than the uncropped input size.
+ *
+ * As the number of phases/taps, used to select the correct equations to compute
+ * the ratio, depends on the ratio, we start with the 4-tap mode equations to
+ * compute an approximation of the ratio, and switch to the 7-tap mode equations
+ * if the approximation is higher than the ratio threshold.
+ *
+ * As the 7-tap mode equations will return a ratio smaller than or equal to the
+ * 4-tap mode equations, the resulting ratio could become lower than or equal to
+ * the ratio threshold. This 'equations loop' isn't an issue as long as the
+ * correct equations are used to compute the final input size. Starting with the
+ * 4-tap mode equations ensure that, in case of values resulting in a 'ratio
+ * loop', the smallest of the ratio values will be used, never exceeding the
+ * requested input size.
*
* We first clamp the output size according to the hardware capabilitie to avoid
* auto-cropping the input more than required to satisfy the TRM equations. The
@@ -775,6 +806,8 @@ static void resizer_calc_ratios(struct isp_res_device *res,
unsigned int max_width;
unsigned int max_height;
unsigned int width_alignment;
+ unsigned int width;
+ unsigned int height;
/*
* Clamp the output height based on the hardware capabilities and
@@ -786,19 +819,22 @@ static void resizer_calc_ratios(struct isp_res_device *res,
max_height = min_t(unsigned int, max_height, MAX_OUT_HEIGHT);
output->height = clamp(output->height, min_height, max_height);
- ratio->vert = ((input->height - 7) * 256 - 32 - 64 * spv)
+ ratio->vert = ((input->height - 4) * 256 + 255 - 16 - 32 * spv)
/ (output->height - 1);
+ if (ratio->vert > MID_RESIZE_VALUE)
+ ratio->vert = ((input->height - 7) * 256 + 255 - 32 - 64 * spv)
+ / (output->height - 1);
ratio->vert = clamp_t(unsigned int, ratio->vert,
MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
if (ratio->vert <= MID_RESIZE_VALUE) {
upscaled_height = (output->height - 1) * ratio->vert
+ 32 * spv + 16;
- input->height = (upscaled_height >> 8) + 4;
+ height = (upscaled_height >> 8) + 4;
} else {
upscaled_height = (output->height - 1) * ratio->vert
+ 64 * spv + 32;
- input->height = (upscaled_height >> 8) + 7;
+ height = (upscaled_height >> 8) + 7;
}
/*
@@ -854,20 +890,29 @@ static void resizer_calc_ratios(struct isp_res_device *res,
max_width & ~(width_alignment - 1));
output->width = ALIGN(output->width, width_alignment);
- ratio->horz = ((input->width - 7) * 256 - 32 - 64 * sph)
+ ratio->horz = ((input->width - 7) * 256 + 255 - 16 - 32 * sph)
/ (output->width - 1);
+ if (ratio->horz > MID_RESIZE_VALUE)
+ ratio->horz = ((input->width - 7) * 256 + 255 - 32 - 64 * sph)
+ / (output->width - 1);
ratio->horz = clamp_t(unsigned int, ratio->horz,
MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
if (ratio->horz <= MID_RESIZE_VALUE) {
upscaled_width = (output->width - 1) * ratio->horz
+ 32 * sph + 16;
- input->width = (upscaled_width >> 8) + 7;
+ width = (upscaled_width >> 8) + 7;
} else {
upscaled_width = (output->width - 1) * ratio->horz
+ 64 * sph + 32;
- input->width = (upscaled_width >> 8) + 7;
+ width = (upscaled_width >> 8) + 7;
}
+
+ /* Center the new crop rectangle. */
+ input->left += (input->width - width) / 2;
+ input->top += (input->height - height) / 2;
+ input->width = width;
+ input->height = height;
}
/*
diff --git a/drivers/media/video/omap3isp/ispstat.h b/drivers/media/video/omap3isp/ispstat.h
index 820950c9ef46..d86da94fa50d 100644
--- a/drivers/media/video/omap3isp/ispstat.h
+++ b/drivers/media/video/omap3isp/ispstat.h
@@ -131,9 +131,9 @@ struct ispstat {
struct ispstat_generic_config {
/*
* Fields must be in the same order as in:
- * - isph3a_aewb_config
- * - isph3a_af_config
- * - isphist_config
+ * - omap3isp_h3a_aewb_config
+ * - omap3isp_h3a_af_config
+ * - omap3isp_hist_config
*/
u32 buf_size;
u16 config_counter;
diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c
index 208a7ec739d7..9cd8f1aa567b 100644
--- a/drivers/media/video/omap3isp/ispvideo.c
+++ b/drivers/media/video/omap3isp/ispvideo.c
@@ -47,29 +47,59 @@
static struct isp_format_info formats[] = {
{ V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
- V4L2_MBUS_FMT_Y8_1X8, V4L2_PIX_FMT_GREY, 8, },
+ V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
+ V4L2_PIX_FMT_GREY, 8, },
+ { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
+ V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
+ V4L2_PIX_FMT_Y10, 10, },
+ { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
+ V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
+ V4L2_PIX_FMT_Y12, 12, },
+ { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+ V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+ V4L2_PIX_FMT_SBGGR8, 8, },
+ { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+ V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+ V4L2_PIX_FMT_SGBRG8, 8, },
+ { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+ V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+ V4L2_PIX_FMT_SGRBG8, 8, },
+ { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+ V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+ V4L2_PIX_FMT_SRGGB8, 8, },
{ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
- V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
+ V4L2_MBUS_FMT_SGRBG10_1X10, 0,
+ V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
{ V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
- V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 10, },
+ V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
+ V4L2_PIX_FMT_SBGGR10, 10, },
{ V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
- V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 10, },
+ V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
+ V4L2_PIX_FMT_SGBRG10, 10, },
{ V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
- V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 10, },
+ V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
+ V4L2_PIX_FMT_SGRBG10, 10, },
{ V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
- V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 10, },
+ V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
+ V4L2_PIX_FMT_SRGGB10, 10, },
{ V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
- V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 12, },
+ V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
+ V4L2_PIX_FMT_SBGGR12, 12, },
{ V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
- V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 12, },
+ V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
+ V4L2_PIX_FMT_SGBRG12, 12, },
{ V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
- V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 12, },
+ V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
+ V4L2_PIX_FMT_SGRBG12, 12, },
{ V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
- V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 12, },
+ V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
+ V4L2_PIX_FMT_SRGGB12, 12, },
{ V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
- V4L2_MBUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 16, },
+ V4L2_MBUS_FMT_UYVY8_1X16, 0,
+ V4L2_PIX_FMT_UYVY, 16, },
{ V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
- V4L2_MBUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 16, },
+ V4L2_MBUS_FMT_YUYV8_1X16, 0,
+ V4L2_PIX_FMT_YUYV, 16, },
};
const struct isp_format_info *
@@ -86,6 +116,37 @@ omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
}
/*
+ * Decide whether desired output pixel code can be obtained with
+ * the lane shifter by shifting the input pixel code.
+ * @in: input pixelcode to shifter
+ * @out: output pixelcode from shifter
+ * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
+ *
+ * return true if the combination is possible
+ * return false otherwise
+ */
+static bool isp_video_is_shiftable(enum v4l2_mbus_pixelcode in,
+ enum v4l2_mbus_pixelcode out,
+ unsigned int additional_shift)
+{
+ const struct isp_format_info *in_info, *out_info;
+
+ if (in == out)
+ return true;
+
+ in_info = omap3isp_video_format_info(in);
+ out_info = omap3isp_video_format_info(out);
+
+ if ((in_info->flavor == 0) || (out_info->flavor == 0))
+ return false;
+
+ if (in_info->flavor != out_info->flavor)
+ return false;
+
+ return in_info->bpp - out_info->bpp + additional_shift <= 6;
+}
+
+/*
* isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
* @video: ISP video instance
* @mbus: v4l2_mbus_framefmt format (input)
@@ -235,6 +296,7 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
return -EPIPE;
while (1) {
+ unsigned int shifter_link;
/* Retrieve the sink format */
pad = &subdev->entity.pads[0];
if (!(pad->flags & MEDIA_PAD_FL_SINK))
@@ -263,6 +325,10 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
return -ENOSPC;
}
+ /* If sink pad is on CCDC, the link has the lane shifter
+ * in the middle of it. */
+ shifter_link = subdev == &isp->isp_ccdc.subdev;
+
/* Retrieve the source format */
pad = media_entity_remote_source(pad);
if (pad == NULL ||
@@ -278,10 +344,24 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
return -EPIPE;
/* Check if the two ends match */
- if (fmt_source.format.code != fmt_sink.format.code ||
- fmt_source.format.width != fmt_sink.format.width ||
+ if (fmt_source.format.width != fmt_sink.format.width ||
fmt_source.format.height != fmt_sink.format.height)
return -EPIPE;
+
+ if (shifter_link) {
+ unsigned int parallel_shift = 0;
+ if (isp->isp_ccdc.input == CCDC_INPUT_PARALLEL) {
+ struct isp_parallel_platform_data *pdata =
+ &((struct isp_v4l2_subdevs_group *)
+ subdev->host_priv)->bus.parallel;
+ parallel_shift = pdata->data_lane_shift * 2;
+ }
+ if (!isp_video_is_shiftable(fmt_source.format.code,
+ fmt_sink.format.code,
+ parallel_shift))
+ return -EPIPE;
+ } else if (fmt_source.format.code != fmt_sink.format.code)
+ return -EPIPE;
}
return 0;
diff --git a/drivers/media/video/omap3isp/ispvideo.h b/drivers/media/video/omap3isp/ispvideo.h
index 524a1acd0906..911bea64e78a 100644
--- a/drivers/media/video/omap3isp/ispvideo.h
+++ b/drivers/media/video/omap3isp/ispvideo.h
@@ -49,6 +49,8 @@ struct v4l2_pix_format;
* bits. Identical to @code if the format is 10 bits wide or less.
* @uncompressed: V4L2 media bus format code for the corresponding uncompressed
* format. Identical to @code if the format is not DPCM compressed.
+ * @flavor: V4L2 media bus format code for the same pixel layout but
+ * shifted to be 8 bits per pixel. =0 if format is not shiftable.
* @pixelformat: V4L2 pixel format FCC identifier
* @bpp: Bits per pixel
*/
@@ -56,6 +58,7 @@ struct isp_format_info {
enum v4l2_mbus_pixelcode code;
enum v4l2_mbus_pixelcode truncated;
enum v4l2_mbus_pixelcode uncompressed;
+ enum v4l2_mbus_pixelcode flavor;
u32 pixelformat;
unsigned int bpp;
};
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 95f8b4e11e46..d142b40ea64e 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -527,7 +527,7 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
if (ret)
return ret;
- if (vb2_is_streaming(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
+ if (vb2_is_busy(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
return -EBUSY;
frame = &ctx->d_frame;
@@ -539,8 +539,10 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
return -EINVAL;
}
- for (i = 0; i < frame->fmt->colplanes; i++)
- frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height;
+ for (i = 0; i < frame->fmt->colplanes; i++) {
+ frame->payload[i] =
+ (pix->width * pix->height * frame->fmt->depth[i]) >> 3;
+ }
/* Output DMA frame pixel size and offsets. */
frame->f_width = pix->plane_fmt[0].bytesperline * 8
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 6c919b38a3d8..dc91a8511af6 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -361,10 +361,20 @@ static void fimc_capture_irq_handler(struct fimc_dev *fimc)
{
struct fimc_vid_cap *cap = &fimc->vid_cap;
struct fimc_vid_buffer *v_buf;
+ struct timeval *tv;
+ struct timespec ts;
if (!list_empty(&cap->active_buf_q) &&
test_bit(ST_CAPT_RUN, &fimc->state)) {
+ ktime_get_real_ts(&ts);
+
v_buf = 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++;
+
vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
}
@@ -758,7 +768,7 @@ static void fimc_unlock(struct vb2_queue *vq)
mutex_unlock(&ctx->fimc_dev->lock);
}
-struct vb2_ops fimc_qops = {
+static struct vb2_ops fimc_qops = {
.queue_setup = fimc_queue_setup,
.buf_prepare = fimc_buf_prepare,
.buf_queue = fimc_buf_queue,
@@ -927,23 +937,23 @@ int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
pix->num_planes = fmt->memplanes;
pix->colorspace = V4L2_COLORSPACE_JPEG;
- for (i = 0; i < pix->num_planes; ++i) {
- int bpl = pix->plane_fmt[i].bytesperline;
- dbg("[%d] bpl: %d, depth: %d, w: %d, h: %d",
- i, bpl, fmt->depth[i], pix->width, pix->height);
+ for (i = 0; i < pix->num_planes; ++i) {
+ u32 bpl = pix->plane_fmt[i].bytesperline;
+ u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
- if (!bpl || (bpl * 8 / fmt->depth[i]) > pix->width)
- bpl = (pix->width * fmt->depth[0]) >> 3;
+ if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
+ bpl = pix->width; /* Planar */
- if (!pix->plane_fmt[i].sizeimage)
- pix->plane_fmt[i].sizeimage = pix->height * bpl;
+ if (fmt->colplanes == 1 && /* Packed */
+ (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
+ bpl = (pix->width * fmt->depth[0]) / 8;
- pix->plane_fmt[i].bytesperline = bpl;
+ if (i == 0) /* Same bytesperline for each plane. */
+ mod_x = bpl;
- dbg("[%d]: bpl: %d, sizeimage: %d",
- i, pix->plane_fmt[i].bytesperline,
- pix->plane_fmt[i].sizeimage);
+ pix->plane_fmt[i].bytesperline = mod_x;
+ *sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
}
return 0;
@@ -965,7 +975,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
- if (vb2_is_streaming(vq)) {
+ if (vb2_is_busy(vq)) {
v4l2_err(&fimc->m2m.v4l2_dev, "queue (%d) busy\n", f->type);
return -EBUSY;
}
@@ -985,8 +995,10 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
if (!frame->fmt)
return -EINVAL;
- for (i = 0; i < frame->fmt->colplanes; i++)
- frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height;
+ for (i = 0; i < frame->fmt->colplanes; i++) {
+ frame->payload[i] =
+ (pix->width * pix->height * frame->fmt->depth[i]) / 8;
+ }
frame->f_width = pix->plane_fmt[0].bytesperline * 8 /
frame->fmt->depth[0];
@@ -1750,7 +1762,7 @@ static int __devexit fimc_remove(struct platform_device *pdev)
}
/* Image pixel limits, similar across several FIMC HW revisions. */
-static struct fimc_pix_limit s5p_pix_limit[3] = {
+static struct fimc_pix_limit s5p_pix_limit[4] = {
[0] = {
.scaler_en_w = 3264,
.scaler_dis_w = 8192,
@@ -1775,6 +1787,14 @@ static struct fimc_pix_limit s5p_pix_limit[3] = {
.out_rot_en_w = 1280,
.out_rot_dis_w = 1920,
},
+ [3] = {
+ .scaler_en_w = 1920,
+ .scaler_dis_w = 8192,
+ .in_rot_en_h = 1366,
+ .in_rot_dis_w = 8192,
+ .out_rot_en_w = 1366,
+ .out_rot_dis_w = 1920,
+ },
};
static struct samsung_fimc_variant fimc0_variant_s5p = {
@@ -1827,7 +1847,7 @@ static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
.pix_limit = &s5p_pix_limit[2],
};
-static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
+static struct samsung_fimc_variant fimc0_variant_exynos4 = {
.pix_hoff = 1,
.has_inp_rot = 1,
.has_out_rot = 1,
@@ -1840,7 +1860,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
.pix_limit = &s5p_pix_limit[1],
};
-static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
+static struct samsung_fimc_variant fimc2_variant_exynos4 = {
.pix_hoff = 1,
.has_cistatus2 = 1,
.has_mainscaler_ext = 1,
@@ -1848,7 +1868,7 @@ static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
.min_out_pixsize = 16,
.hor_offs_align = 1,
.out_buf_count = 32,
- .pix_limit = &s5p_pix_limit[2],
+ .pix_limit = &s5p_pix_limit[3],
};
/* S5PC100 */
@@ -1874,12 +1894,12 @@ static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
};
/* S5PV310, S5PC210 */
-static struct samsung_fimc_driverdata fimc_drvdata_s5pv310 = {
+static struct samsung_fimc_driverdata fimc_drvdata_exynos4 = {
.variant = {
- [0] = &fimc0_variant_s5pv310,
- [1] = &fimc0_variant_s5pv310,
- [2] = &fimc0_variant_s5pv310,
- [3] = &fimc2_variant_s5pv310,
+ [0] = &fimc0_variant_exynos4,
+ [1] = &fimc0_variant_exynos4,
+ [2] = &fimc0_variant_exynos4,
+ [3] = &fimc2_variant_exynos4,
},
.num_entities = 4,
.lclk_frequency = 166000000UL,
@@ -1893,8 +1913,8 @@ static struct platform_device_id fimc_driver_ids[] = {
.name = "s5pv210-fimc",
.driver_data = (unsigned long)&fimc_drvdata_s5pv210,
}, {
- .name = "s5pv310-fimc",
- .driver_data = (unsigned long)&fimc_drvdata_s5pv310,
+ .name = "exynos4-fimc",
+ .driver_data = (unsigned long)&fimc_drvdata_exynos4,
},
{},
};
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 3fe54bf41142..134e86bf6d97 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -922,7 +922,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
/* Try 2560x1920, 1280x960, 640x480, 320x240 */
mf.width = 2560 >> shift;
mf.height = 1920 >> shift;
- ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+ ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
s_mbus_fmt, &mf);
if (ret < 0)
return ret;
@@ -1224,7 +1224,7 @@ static int client_s_fmt(struct soc_camera_device *icd,
struct v4l2_cropcap cap;
int ret;
- ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+ ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
s_mbus_fmt, mf);
if (ret < 0)
return ret;
@@ -1254,7 +1254,7 @@ static int client_s_fmt(struct soc_camera_device *icd,
tmp_h = min(2 * tmp_h, max_height);
mf->width = tmp_w;
mf->height = tmp_h;
- ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+ ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
s_mbus_fmt, mf);
dev_geo(dev, "Camera scaled to %ux%u\n",
mf->width, mf->height);
@@ -1658,7 +1658,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
mf.code = xlate->code;
mf.colorspace = pix->colorspace;
- ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video, try_mbus_fmt, &mf);
+ ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, try_mbus_fmt, &mf);
if (ret < 0)
return ret;
@@ -1682,7 +1682,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
*/
mf.width = 2560;
mf.height = 1920;
- ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+ ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
try_mbus_fmt, &mf);
if (ret < 0) {
/* Shouldn't actually happen... */
diff --git a/drivers/media/video/sh_mobile_csi2.c b/drivers/media/video/sh_mobile_csi2.c
index dd1b81b1442b..98b87481fa94 100644
--- a/drivers/media/video/sh_mobile_csi2.c
+++ b/drivers/media/video/sh_mobile_csi2.c
@@ -38,6 +38,8 @@ struct sh_csi2 {
void __iomem *base;
struct platform_device *pdev;
struct sh_csi2_client_config *client;
+ unsigned long (*query_bus_param)(struct soc_camera_device *);
+ int (*set_bus_param)(struct soc_camera_device *, unsigned long);
};
static int sh_csi2_try_fmt(struct v4l2_subdev *sd,
@@ -208,6 +210,7 @@ static int sh_csi2_notify(struct notifier_block *nb,
case BUS_NOTIFY_BOUND_DRIVER:
snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s%s",
dev_name(v4l2_dev->dev), ".mipi-csi");
+ priv->subdev.grp_id = (long)icd;
ret = v4l2_device_register_subdev(v4l2_dev, &priv->subdev);
dev_dbg(dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret);
if (ret < 0)
@@ -215,6 +218,8 @@ static int sh_csi2_notify(struct notifier_block *nb,
priv->client = pdata->clients + i;
+ priv->set_bus_param = icd->ops->set_bus_param;
+ priv->query_bus_param = icd->ops->query_bus_param;
icd->ops->set_bus_param = sh_csi2_set_bus_param;
icd->ops->query_bus_param = sh_csi2_query_bus_param;
@@ -226,8 +231,10 @@ static int sh_csi2_notify(struct notifier_block *nb,
priv->client = NULL;
/* Driver is about to be unbound */
- icd->ops->set_bus_param = NULL;
- icd->ops->query_bus_param = NULL;
+ icd->ops->set_bus_param = priv->set_bus_param;
+ icd->ops->query_bus_param = priv->query_bus_param;
+ priv->set_bus_param = NULL;
+ priv->query_bus_param = NULL;
v4l2_device_unregister_subdev(&priv->subdev);
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 46284489e4eb..ddb4c091dedc 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -136,11 +136,50 @@ unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
}
EXPORT_SYMBOL(soc_camera_apply_sensor_flags);
+#define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
+ ((x) >> 24) & 0xff
+
+static int soc_camera_try_fmt(struct soc_camera_device *icd,
+ struct v4l2_format *f)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ int ret;
+
+ dev_dbg(&icd->dev, "TRY_FMT(%c%c%c%c, %ux%u)\n",
+ pixfmtstr(pix->pixelformat), pix->width, pix->height);
+
+ pix->bytesperline = 0;
+ pix->sizeimage = 0;
+
+ ret = ici->ops->try_fmt(icd, f);
+ if (ret < 0)
+ return ret;
+
+ if (!pix->sizeimage) {
+ if (!pix->bytesperline) {
+ const struct soc_camera_format_xlate *xlate;
+
+ xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+ if (!xlate)
+ return -EINVAL;
+
+ ret = soc_mbus_bytes_per_line(pix->width,
+ xlate->host_fmt);
+ if (ret > 0)
+ pix->bytesperline = ret;
+ }
+ if (pix->bytesperline)
+ pix->sizeimage = pix->bytesperline * pix->height;
+ }
+
+ return 0;
+}
+
static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct soc_camera_device *icd = file->private_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
WARN_ON(priv != file->private_data);
@@ -149,7 +188,7 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL;
/* limit format to hardware capabilities */
- return ici->ops->try_fmt(icd, f);
+ return soc_camera_try_fmt(icd, f);
}
static int soc_camera_enum_input(struct file *file, void *priv,
@@ -362,9 +401,6 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd)
icd->user_formats = NULL;
}
-#define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
- ((x) >> 24) & 0xff
-
/* Called with .vb_lock held, or from the first open(2), see comment there */
static int soc_camera_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
@@ -377,7 +413,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
pixfmtstr(pix->pixelformat), pix->width, pix->height);
/* We always call try_fmt() before set_fmt() or set_crop() */
- ret = ici->ops->try_fmt(icd, f);
+ ret = soc_camera_try_fmt(icd, f);
if (ret < 0)
return ret;
@@ -996,10 +1032,11 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd)
{
struct i2c_client *client =
to_i2c_client(to_soc_camera_control(icd));
+ struct i2c_adapter *adap = client->adapter;
dev_set_drvdata(&icd->dev, NULL);
v4l2_device_unregister_subdev(i2c_get_clientdata(client));
i2c_unregister_device(client);
- i2c_put_adapter(client->adapter);
+ i2c_put_adapter(adap);
}
#else
#define soc_camera_init_i2c(icd, icl) (-ENODEV)
@@ -1071,6 +1108,9 @@ static int soc_camera_probe(struct device *dev)
}
}
+ sd = soc_camera_to_subdev(icd);
+ sd->grp_id = (long)icd;
+
/* At this point client .probe() should have run already */
ret = soc_camera_init_user_formats(icd);
if (ret < 0)
@@ -1092,7 +1132,6 @@ static int soc_camera_probe(struct device *dev)
goto evidstart;
/* Try to improve our guess of a reasonable window format */
- sd = soc_camera_to_subdev(icd);
if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
icd->user_width = mf.width;
icd->user_height = mf.height;
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index 5d4cf3b3d435..22fa8202d5ca 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -171,7 +171,7 @@ static int tda9840_probe(struct i2c_client *client,
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
- sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+ sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
if (sd == NULL)
return -ENOMEM;
v4l2_i2c_subdev_init(sd, client, &tda9840_ops);
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index 19621ed523ec..827425c5b866 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -152,7 +152,7 @@ static int tea6415c_probe(struct i2c_client *client,
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
- sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+ sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
if (sd == NULL)
return -ENOMEM;
v4l2_i2c_subdev_init(sd, client, &tea6415c_ops);
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 5ea840401f21..f350b6c24500 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -125,7 +125,7 @@ static int tea6420_probe(struct i2c_client *client,
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
- sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+ sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
if (sd == NULL)
return -ENOMEM;
v4l2_i2c_subdev_init(sd, client, &tea6420_ops);
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c
index f8138c75be8b..1aab96a88203 100644
--- a/drivers/media/video/upd64031a.c
+++ b/drivers/media/video/upd64031a.c
@@ -230,7 +230,7 @@ static int upd64031a_probe(struct i2c_client *client,
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
- state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
if (state == NULL)
return -ENOMEM;
sd = &state->sd;
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c
index 28e0e6b6ca84..9bbe61700fd5 100644
--- a/drivers/media/video/upd64083.c
+++ b/drivers/media/video/upd64083.c
@@ -202,7 +202,7 @@ static int upd64083_probe(struct i2c_client *client,
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
- state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct upd64083_state), GFP_KERNEL);
if (state == NULL)
return -ENOMEM;
sd = &state->sd;
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 498e6742579e..6dc7196296b3 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -389,7 +389,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
video_get(vdev);
mutex_unlock(&videodev_lock);
#if defined(CONFIG_MEDIA_CONTROLLER)
- if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
+ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+ vdev->vfl_type != VFL_TYPE_SUBDEV) {
entity = media_entity_get(&vdev->entity);
if (!entity) {
ret = -EBUSY;
@@ -415,7 +416,8 @@ err:
/* decrease the refcount in case of an error */
if (ret) {
#if defined(CONFIG_MEDIA_CONTROLLER)
- if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
+ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+ vdev->vfl_type != VFL_TYPE_SUBDEV)
media_entity_put(entity);
#endif
video_put(vdev);
@@ -437,7 +439,8 @@ static int v4l2_release(struct inode *inode, struct file *filp)
mutex_unlock(vdev->lock);
}
#if defined(CONFIG_MEDIA_CONTROLLER)
- if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
+ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+ vdev->vfl_type != VFL_TYPE_SUBDEV)
media_entity_put(&vdev->entity);
#endif
/* decrease the refcount unconditionally since the release()
@@ -686,7 +689,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
#if defined(CONFIG_MEDIA_CONTROLLER)
/* Part 5: Register the entity. */
- if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
+ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+ vdev->vfl_type != VFL_TYPE_SUBDEV) {
vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
vdev->entity.name = vdev->name;
vdev->entity.v4l.major = VIDEO_MAJOR;
@@ -733,7 +737,8 @@ void video_unregister_device(struct video_device *vdev)
return;
#if defined(CONFIG_MEDIA_CONTROLLER)
- if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
+ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+ vdev->vfl_type != VFL_TYPE_SUBDEV)
media_device_unregister_entity(&vdev->entity);
#endif
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index 5aeaf876ba9b..4aae501f02d0 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -155,8 +155,10 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
sd->v4l2_dev = v4l2_dev;
if (sd->internal_ops && sd->internal_ops->registered) {
err = sd->internal_ops->registered(sd);
- if (err)
+ if (err) {
+ module_put(sd->owner);
return err;
+ }
}
/* This just returns 0 if either of the two args is NULL */
@@ -164,6 +166,7 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
if (err) {
if (sd->internal_ops && sd->internal_ops->unregistered)
sd->internal_ops->unregistered(sd);
+ module_put(sd->owner);
return err;
}
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index 0b8064490676..812729ebf09e 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -155,25 +155,25 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
switch (cmd) {
case VIDIOC_QUERYCTRL:
- return v4l2_subdev_queryctrl(sd, arg);
+ return v4l2_queryctrl(sd->ctrl_handler, arg);
case VIDIOC_QUERYMENU:
- return v4l2_subdev_querymenu(sd, arg);
+ return v4l2_querymenu(sd->ctrl_handler, arg);
case VIDIOC_G_CTRL:
- return v4l2_subdev_g_ctrl(sd, arg);
+ return v4l2_g_ctrl(sd->ctrl_handler, arg);
case VIDIOC_S_CTRL:
- return v4l2_subdev_s_ctrl(sd, arg);
+ return v4l2_s_ctrl(sd->ctrl_handler, arg);
case VIDIOC_G_EXT_CTRLS:
- return v4l2_subdev_g_ext_ctrls(sd, arg);
+ return v4l2_g_ext_ctrls(sd->ctrl_handler, arg);
case VIDIOC_S_EXT_CTRLS:
- return v4l2_subdev_s_ext_ctrls(sd, arg);
+ return v4l2_s_ext_ctrls(sd->ctrl_handler, arg);
case VIDIOC_TRY_EXT_CTRLS:
- return v4l2_subdev_try_ext_ctrls(sd, arg);
+ return v4l2_try_ext_ctrls(sd->ctrl_handler, arg);
case VIDIOC_DQEVENT:
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c
index c4742fc15529..c9691115f2d2 100644
--- a/drivers/media/video/videobuf-dma-contig.c
+++ b/drivers/media/video/videobuf-dma-contig.c
@@ -300,7 +300,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
retval = remap_pfn_range(vma, vma->vm_start,
- PFN_DOWN(virt_to_phys(mem->vaddr)),
+ mem->dma_handle >> PAGE_SHIFT,
size, vma->vm_page_prot);
if (retval) {
dev_err(q->dev, "mmap: remap failed with error %d. ", retval);
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index 6698c77e0f64..6ba1461d51ef 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -37,6 +37,9 @@ module_param(debug, int, 0644);
#define call_qop(q, op, args...) \
(((q)->ops->op) ? ((q)->ops->op(args)) : 0)
+#define V4L2_BUFFER_STATE_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
+ V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR)
+
/**
* __vb2_buf_mem_alloc() - allocate video memory for the given buffer
*/
@@ -51,7 +54,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb,
for (plane = 0; plane < vb->num_planes; ++plane) {
mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
plane_sizes[plane]);
- if (!mem_priv)
+ if (IS_ERR_OR_NULL(mem_priv))
goto free;
/* Associate allocator private data with this plane */
@@ -284,7 +287,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
struct vb2_queue *q = vb->vb2_queue;
int ret = 0;
- /* Copy back data such as timestamp, input, etc. */
+ /* Copy back data such as timestamp, flags, input, etc. */
memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
b->input = vb->v4l2_buf.input;
b->reserved = vb->v4l2_buf.reserved;
@@ -313,7 +316,10 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
b->m.userptr = vb->v4l2_planes[0].m.userptr;
}
- b->flags = 0;
+ /*
+ * Clear any buffer state related flags.
+ */
+ b->flags &= ~V4L2_BUFFER_STATE_FLAGS;
switch (vb->state) {
case VB2_BUF_STATE_QUEUED:
@@ -519,6 +525,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
memset(plane_sizes, 0, sizeof(plane_sizes));
memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
+ q->memory = req->memory;
/*
* Ask the driver how many buffers and planes per buffer it requires.
@@ -560,8 +567,6 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
ret = num_buffers;
}
- q->memory = req->memory;
-
/*
* Return the number of successfully allocated buffers
* to the userspace.
@@ -715,6 +720,8 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b,
vb->v4l2_buf.field = b->field;
vb->v4l2_buf.timestamp = b->timestamp;
+ vb->v4l2_buf.input = b->input;
+ vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS;
return 0;
}
diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index 58205d596138..a790a5f8c06f 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -46,7 +46,7 @@ static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
GFP_KERNEL);
if (!buf->vaddr) {
dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
- buf->size);
+ size);
kfree(buf);
return ERR_PTR(-ENOMEM);
}