Merge tag 'media/v5.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media fixes from Mauro Carvalho Chehab: "Some fixes for some platform drivers (rockchip, atmel, omap, daVinci, tegra-cec, coda and rcar). Also includes a fix on one of the V4L2 uAPI doc, explaining a border case" * tag 'media/v5.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: media: rockchip/vpu: Fix/re-order probe-error/remove path media: rockchip/vpu: Initialize mdev->bus_info media: rockchip/vpu: Get vdev from the file arg in vidioc_querycap() media: rockchip/vpu: Add missing dont_use_autosuspend() calls media: rockchip/vpu: Do not request id 0 for our video device media: tegra-cec: fix cec_notifier_parse_hdmi_phandle return check media: davinci/vpbe: array underflow in vpbe_enum_outputs() media: field-order.rst: clarify FIELD_ANY and FIELD_NONE media: staging/imx: add media device to capture register media: rcar-csi2: Propagate the FLD signal for NTSC and PAL media: rcar-csi2: restart CSI-2 link if error is detected media: omap_vout: potential buffer overflow in vidioc_dqbuf() media: coda: fix unset field and fail on invalid field in buf_prepare media: atmel: atmel-isc: fix asd memory allocation media: atmel: atmel-isc: fix INIT_WORK misplacement media: atmel: atmel-isc: limit incoming pixels per frame
This commit is contained in:
@@ -37,6 +37,25 @@
|
||||
#define ISC_PFG_CFG0_BPS_TWELVE (0x0 << 28)
|
||||
#define ISC_PFE_CFG0_BPS_MASK GENMASK(30, 28)
|
||||
|
||||
#define ISC_PFE_CFG0_COLEN BIT(12)
|
||||
#define ISC_PFE_CFG0_ROWEN BIT(13)
|
||||
|
||||
/* ISC Parallel Front End Configuration 1 Register */
|
||||
#define ISC_PFE_CFG1 0x00000010
|
||||
|
||||
#define ISC_PFE_CFG1_COLMIN(v) ((v))
|
||||
#define ISC_PFE_CFG1_COLMIN_MASK GENMASK(15, 0)
|
||||
#define ISC_PFE_CFG1_COLMAX(v) ((v) << 16)
|
||||
#define ISC_PFE_CFG1_COLMAX_MASK GENMASK(31, 16)
|
||||
|
||||
/* ISC Parallel Front End Configuration 2 Register */
|
||||
#define ISC_PFE_CFG2 0x00000014
|
||||
|
||||
#define ISC_PFE_CFG2_ROWMIN(v) ((v))
|
||||
#define ISC_PFE_CFG2_ROWMIN_MASK GENMASK(15, 0)
|
||||
#define ISC_PFE_CFG2_ROWMAX(v) ((v) << 16)
|
||||
#define ISC_PFE_CFG2_ROWMAX_MASK GENMASK(31, 16)
|
||||
|
||||
/* ISC Clock Enable Register */
|
||||
#define ISC_CLKEN 0x00000018
|
||||
|
||||
|
@@ -721,6 +721,40 @@ static void isc_start_dma(struct isc_device *isc)
|
||||
u32 sizeimage = isc->fmt.fmt.pix.sizeimage;
|
||||
u32 dctrl_dview;
|
||||
dma_addr_t addr0;
|
||||
u32 h, w;
|
||||
|
||||
h = isc->fmt.fmt.pix.height;
|
||||
w = isc->fmt.fmt.pix.width;
|
||||
|
||||
/*
|
||||
* In case the sensor is not RAW, it will output a pixel (12-16 bits)
|
||||
* with two samples on the ISC Data bus (which is 8-12)
|
||||
* ISC will count each sample, so, we need to multiply these values
|
||||
* by two, to get the real number of samples for the required pixels.
|
||||
*/
|
||||
if (!ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) {
|
||||
h <<= 1;
|
||||
w <<= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We limit the column/row count that the ISC will output according
|
||||
* to the configured resolution that we want.
|
||||
* This will avoid the situation where the sensor is misconfigured,
|
||||
* sending more data, and the ISC will just take it and DMA to memory,
|
||||
* causing corruption.
|
||||
*/
|
||||
regmap_write(regmap, ISC_PFE_CFG1,
|
||||
(ISC_PFE_CFG1_COLMIN(0) & ISC_PFE_CFG1_COLMIN_MASK) |
|
||||
(ISC_PFE_CFG1_COLMAX(w - 1) & ISC_PFE_CFG1_COLMAX_MASK));
|
||||
|
||||
regmap_write(regmap, ISC_PFE_CFG2,
|
||||
(ISC_PFE_CFG2_ROWMIN(0) & ISC_PFE_CFG2_ROWMIN_MASK) |
|
||||
(ISC_PFE_CFG2_ROWMAX(h - 1) & ISC_PFE_CFG2_ROWMAX_MASK));
|
||||
|
||||
regmap_update_bits(regmap, ISC_PFE_CFG0,
|
||||
ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN,
|
||||
ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN);
|
||||
|
||||
addr0 = vb2_dma_contig_plane_dma_addr(&isc->cur_frm->vb.vb2_buf, 0);
|
||||
regmap_write(regmap, ISC_DAD0, addr0);
|
||||
@@ -1965,6 +1999,8 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
|
||||
struct vb2_queue *q = &isc->vb2_vidq;
|
||||
int ret;
|
||||
|
||||
INIT_WORK(&isc->awb_work, isc_awb_work);
|
||||
|
||||
ret = v4l2_device_register_subdev_nodes(&isc->v4l2_dev);
|
||||
if (ret < 0) {
|
||||
v4l2_err(&isc->v4l2_dev, "Failed to register subdev nodes\n");
|
||||
@@ -2018,8 +2054,6 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
|
||||
return ret;
|
||||
}
|
||||
|
||||
INIT_WORK(&isc->awb_work, isc_awb_work);
|
||||
|
||||
/* Register video device */
|
||||
strscpy(vdev->name, ATMEL_ISC_NAME, sizeof(vdev->name));
|
||||
vdev->release = video_device_release_empty;
|
||||
@@ -2135,8 +2169,11 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
|
||||
break;
|
||||
}
|
||||
|
||||
subdev_entity->asd = devm_kzalloc(dev,
|
||||
sizeof(*subdev_entity->asd), GFP_KERNEL);
|
||||
/* asd will be freed by the subsystem once it's added to the
|
||||
* notifier list
|
||||
*/
|
||||
subdev_entity->asd = kzalloc(sizeof(*subdev_entity->asd),
|
||||
GFP_KERNEL);
|
||||
if (!subdev_entity->asd) {
|
||||
of_node_put(rem);
|
||||
ret = -ENOMEM;
|
||||
@@ -2284,6 +2321,7 @@ static int atmel_isc_probe(struct platform_device *pdev)
|
||||
subdev_entity->asd);
|
||||
if (ret) {
|
||||
fwnode_handle_put(subdev_entity->asd->match.fwnode);
|
||||
kfree(subdev_entity->asd);
|
||||
goto cleanup_subdev;
|
||||
}
|
||||
|
||||
|
@@ -1515,10 +1515,20 @@ static int coda_queue_setup(struct vb2_queue *vq,
|
||||
|
||||
static int coda_buf_prepare(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 coda_q_data *q_data;
|
||||
|
||||
q_data = get_q_data(ctx, vb->vb2_queue->type);
|
||||
if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
|
||||
if (vbuf->field == V4L2_FIELD_ANY)
|
||||
vbuf->field = V4L2_FIELD_NONE;
|
||||
if (vbuf->field != V4L2_FIELD_NONE) {
|
||||
v4l2_warn(&ctx->dev->v4l2_dev,
|
||||
"%s field isn't supported\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
|
||||
v4l2_warn(&ctx->dev->v4l2_dev,
|
||||
|
@@ -104,7 +104,7 @@ static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev,
|
||||
struct v4l2_output *output)
|
||||
{
|
||||
struct vpbe_config *cfg = vpbe_dev->cfg;
|
||||
int temp_index = output->index;
|
||||
unsigned int temp_index = output->index;
|
||||
|
||||
if (temp_index >= cfg->num_outputs)
|
||||
return -EINVAL;
|
||||
|
@@ -1527,23 +1527,20 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
|
||||
unsigned long size;
|
||||
struct videobuf_buffer *vb;
|
||||
|
||||
vb = q->bufs[b->index];
|
||||
|
||||
if (!vout->streaming)
|
||||
return -EINVAL;
|
||||
|
||||
if (file->f_flags & O_NONBLOCK)
|
||||
/* Call videobuf_dqbuf for non blocking mode */
|
||||
ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
|
||||
else
|
||||
/* Call videobuf_dqbuf for blocking mode */
|
||||
ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
|
||||
ret = videobuf_dqbuf(q, b, !!(file->f_flags & O_NONBLOCK));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vb = q->bufs[b->index];
|
||||
|
||||
addr = (unsigned long) vout->buf_phy_addr[vb->i];
|
||||
size = (unsigned long) vb->size;
|
||||
dma_unmap_single(vout->vid_dev->v4l2_dev.dev, addr,
|
||||
size, DMA_TO_DEVICE);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
|
||||
|
@@ -68,6 +68,7 @@ struct rcar_csi2;
|
||||
/* Field Detection Control */
|
||||
#define FLD_REG 0x1c
|
||||
#define FLD_FLD_NUM(n) (((n) & 0xff) << 16)
|
||||
#define FLD_DET_SEL(n) (((n) & 0x3) << 4)
|
||||
#define FLD_FLD_EN4 BIT(3)
|
||||
#define FLD_FLD_EN3 BIT(2)
|
||||
#define FLD_FLD_EN2 BIT(1)
|
||||
@@ -84,6 +85,9 @@ struct rcar_csi2;
|
||||
|
||||
/* Interrupt Enable */
|
||||
#define INTEN_REG 0x30
|
||||
#define INTEN_INT_AFIFO_OF BIT(27)
|
||||
#define INTEN_INT_ERRSOTHS BIT(4)
|
||||
#define INTEN_INT_ERRSOTSYNCHS BIT(3)
|
||||
|
||||
/* Interrupt Source Mask */
|
||||
#define INTCLOSE_REG 0x34
|
||||
@@ -475,7 +479,7 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp)
|
||||
static int rcsi2_start_receiver(struct rcar_csi2 *priv)
|
||||
{
|
||||
const struct rcar_csi2_format *format;
|
||||
u32 phycnt, vcdt = 0, vcdt2 = 0;
|
||||
u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0;
|
||||
unsigned int i;
|
||||
int mbps, ret;
|
||||
|
||||
@@ -507,6 +511,16 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
|
||||
vcdt2 |= vcdt_part << ((i % 2) * 16);
|
||||
}
|
||||
|
||||
if (priv->mf.field == V4L2_FIELD_ALTERNATE) {
|
||||
fld = FLD_DET_SEL(1) | FLD_FLD_EN4 | FLD_FLD_EN3 | FLD_FLD_EN2
|
||||
| FLD_FLD_EN;
|
||||
|
||||
if (priv->mf.height == 240)
|
||||
fld |= FLD_FLD_NUM(0);
|
||||
else
|
||||
fld |= FLD_FLD_NUM(1);
|
||||
}
|
||||
|
||||
phycnt = PHYCNT_ENABLECLK;
|
||||
phycnt |= (1 << priv->lanes) - 1;
|
||||
|
||||
@@ -514,6 +528,10 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
|
||||
if (mbps < 0)
|
||||
return mbps;
|
||||
|
||||
/* Enable interrupts. */
|
||||
rcsi2_write(priv, INTEN_REG, INTEN_INT_AFIFO_OF | INTEN_INT_ERRSOTHS
|
||||
| INTEN_INT_ERRSOTSYNCHS);
|
||||
|
||||
/* Init */
|
||||
rcsi2_write(priv, TREF_REG, TREF_TREF);
|
||||
rcsi2_write(priv, PHTC_REG, 0);
|
||||
@@ -549,8 +567,7 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
|
||||
rcsi2_write(priv, PHYCNT_REG, phycnt);
|
||||
rcsi2_write(priv, LINKCNT_REG, LINKCNT_MONITOR_EN |
|
||||
LINKCNT_REG_MONI_PACT_EN | LINKCNT_ICLK_NONSTOP);
|
||||
rcsi2_write(priv, FLD_REG, FLD_FLD_NUM(2) | FLD_FLD_EN4 |
|
||||
FLD_FLD_EN3 | FLD_FLD_EN2 | FLD_FLD_EN);
|
||||
rcsi2_write(priv, FLD_REG, fld);
|
||||
rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ);
|
||||
rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ);
|
||||
|
||||
@@ -675,6 +692,43 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
|
||||
.pad = &rcar_csi2_pad_ops,
|
||||
};
|
||||
|
||||
static irqreturn_t rcsi2_irq(int irq, void *data)
|
||||
{
|
||||
struct rcar_csi2 *priv = data;
|
||||
u32 status, err_status;
|
||||
|
||||
status = rcsi2_read(priv, INTSTATE_REG);
|
||||
err_status = rcsi2_read(priv, INTERRSTATE_REG);
|
||||
|
||||
if (!status)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
rcsi2_write(priv, INTSTATE_REG, status);
|
||||
|
||||
if (!err_status)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
rcsi2_write(priv, INTERRSTATE_REG, err_status);
|
||||
|
||||
dev_info(priv->dev, "Transfer error, restarting CSI-2 receiver\n");
|
||||
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
static irqreturn_t rcsi2_irq_thread(int irq, void *data)
|
||||
{
|
||||
struct rcar_csi2 *priv = data;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
rcsi2_stop(priv);
|
||||
usleep_range(1000, 2000);
|
||||
if (rcsi2_start(priv))
|
||||
dev_warn(priv->dev, "Failed to restart CSI-2 receiver\n");
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Async handling and registration of subdevices and links.
|
||||
*/
|
||||
@@ -947,7 +1001,7 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
int irq;
|
||||
int irq, ret;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
@@ -958,6 +1012,12 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, rcsi2_irq,
|
||||
rcsi2_irq_thread, IRQF_SHARED,
|
||||
KBUILD_MODNAME, priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(priv->rstc))
|
||||
return PTR_ERR(priv->rstc);
|
||||
|
@@ -334,8 +334,8 @@ static int tegra_cec_probe(struct platform_device *pdev)
|
||||
|
||||
hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
|
||||
|
||||
if (!hdmi_dev)
|
||||
return -ENODEV;
|
||||
if (IS_ERR(hdmi_dev))
|
||||
return PTR_ERR(hdmi_dev);
|
||||
|
||||
cec = devm_kzalloc(&pdev->dev, sizeof(struct tegra_cec), GFP_KERNEL);
|
||||
|
||||
|
Reference in New Issue
Block a user