mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
drivers: media: platform: rockchip: cif: sync with develop-4.4
sync with develop-4.4 at commit point:2b8ec827b22abc4a47 Signed-off-by: Allon Huang <allon.huang@rock-chips.com> Change-Id: I1d16e1a176ca8af36d5c8f0d55d747718db5aca0
This commit is contained in:
@@ -33,6 +33,12 @@
|
||||
#define STREAM_PAD_SINK 0
|
||||
#define STREAM_PAD_SOURCE 1
|
||||
|
||||
/*
|
||||
* Round up height when allocate memory so that Rockchip encoder can
|
||||
* use DMA buffer directly, though this may waste a bit of memory.
|
||||
*/
|
||||
#define MEMORY_ALIGN_ROUND_UP_HEIGHT 16
|
||||
|
||||
/* Get xsubs and ysubs for fourcc formats
|
||||
*
|
||||
* @xsubs: horizontal color samples in a 4*4 matrix, for yuv
|
||||
@@ -879,27 +885,37 @@ static void rkcif_stream_stop(struct rkcif_stream *stream)
|
||||
}
|
||||
|
||||
static int rkcif_queue_setup(struct vb2_queue *queue,
|
||||
const void *parg,
|
||||
unsigned int *num_buffers,
|
||||
unsigned int *num_planes,
|
||||
unsigned int sizes[],
|
||||
struct device *alloc_ctxs[])
|
||||
void *alloc_ctxs[])
|
||||
{
|
||||
struct rkcif_stream *stream = queue->drv_priv;
|
||||
struct rkcif_device *dev = stream->cifdev;
|
||||
const struct v4l2_format *pfmt = parg;
|
||||
const struct v4l2_pix_format_mplane *pixm;
|
||||
const struct cif_output_fmt *cif_fmt;
|
||||
u32 i;
|
||||
|
||||
if (pfmt) {
|
||||
pixm = &pfmt->fmt.pix_mp;
|
||||
cif_fmt = find_output_fmt(stream, pixm->pixelformat);
|
||||
} else {
|
||||
pixm = &stream->pixm;
|
||||
cif_fmt = stream->cif_fmt_out;
|
||||
}
|
||||
|
||||
pixm = &stream->pixm;
|
||||
cif_fmt = stream->cif_fmt_out;
|
||||
*num_planes = cif_fmt->mplanes;
|
||||
|
||||
for (i = 0; i < cif_fmt->mplanes; i++) {
|
||||
const struct v4l2_plane_pix_format *plane_fmt;
|
||||
int h = round_up(pixm->height, MEMORY_ALIGN_ROUND_UP_HEIGHT);
|
||||
|
||||
plane_fmt = &pixm->plane_fmt[i];
|
||||
sizes[i] = plane_fmt->sizeimage;
|
||||
sizes[i] = plane_fmt->sizeimage / pixm->height * h;
|
||||
|
||||
alloc_ctxs[i] = dev->alloc_ctx;
|
||||
}
|
||||
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, "%s count %d, size %d\n",
|
||||
@@ -1588,19 +1604,18 @@ static int rkcif_fh_open(struct file *filp)
|
||||
* Because CRU would reset iommu too, so there's not chance
|
||||
* to reset cif once we hold buffers after buf queued
|
||||
*/
|
||||
if (cifdev->chip_id == CHIP_RK1808_CIF)
|
||||
if (cifdev->chip_id == CHIP_RK1808_CIF) {
|
||||
mutex_lock(&cifdev->stream_lock);
|
||||
v4l2_info(&cifdev->v4l2_dev, "fh_cnt: %d\n",
|
||||
atomic_read(&cifdev->fh_cnt));
|
||||
if (!atomic_read(&cifdev->fh_cnt))
|
||||
rkcif_soft_reset(cifdev, true);
|
||||
atomic_inc(&cifdev->fh_cnt);
|
||||
else
|
||||
mutex_unlock(&cifdev->stream_lock);
|
||||
} else {
|
||||
rkcif_soft_reset(cifdev, true);
|
||||
|
||||
ret = vb2_fop_release(file);
|
||||
if (!ret) {
|
||||
ret = v4l2_pipeline_pm_use(&stream->vdev.entity, 0);
|
||||
if (ret < 0)
|
||||
v4l2_err(&cifdev->v4l2_dev,
|
||||
"set pipeline power failed %d\n", ret);
|
||||
}
|
||||
return ret;
|
||||
return v4l2_fh_open(filp);
|
||||
}
|
||||
|
||||
static int rkcif_fh_release(struct file *filp)
|
||||
@@ -1896,7 +1911,6 @@ static int rkcif_register_stream_vdev(struct rkcif_stream *stream,
|
||||
}
|
||||
|
||||
ret = media_entity_init(&vdev->entity, 1, &node->pad, 0);
|
||||
|
||||
if (ret < 0)
|
||||
goto unreg;
|
||||
|
||||
@@ -1954,7 +1968,7 @@ static void rkcif_vb_done_oneframe(struct rkcif_stream *stream,
|
||||
vb2_set_plane_payload(&vb_done->vb2_buf, i,
|
||||
stream->pixm.plane_fmt[i].sizeimage);
|
||||
}
|
||||
vb_done->vb2_buf.timestamp = ktime_get_ns();
|
||||
vb_done->timestamp = ns_to_timeval(ktime_get_ns());
|
||||
vb2_buffer_done(&vb_done->vb2_buf, VB2_BUF_STATE_DONE);
|
||||
}
|
||||
|
||||
|
||||
@@ -585,6 +585,63 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rkcif_iommu_init(struct rkcif_device *cif_dev)
|
||||
{
|
||||
struct iommu_group *group;
|
||||
int ret;
|
||||
|
||||
cif_dev->domain = iommu_domain_alloc(&platform_bus_type);
|
||||
if (!cif_dev->domain)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = iommu_get_dma_cookie(cif_dev->domain);
|
||||
if (ret)
|
||||
goto err_free_domain;
|
||||
|
||||
group = iommu_group_get(cif_dev->dev);
|
||||
if (!group) {
|
||||
group = iommu_group_alloc();
|
||||
if (IS_ERR(group)) {
|
||||
ret = PTR_ERR(group);
|
||||
goto err_put_cookie;
|
||||
}
|
||||
ret = iommu_group_add_device(group, cif_dev->dev);
|
||||
iommu_group_put(group);
|
||||
if (ret)
|
||||
goto err_put_cookie;
|
||||
}
|
||||
iommu_group_put(group);
|
||||
|
||||
ret = iommu_attach_device(cif_dev->domain, cif_dev->dev);
|
||||
if (ret)
|
||||
goto err_put_cookie;
|
||||
if (!common_iommu_setup_dma_ops(cif_dev->dev, 0x10000000, SZ_2G,
|
||||
cif_dev->domain->ops)) {
|
||||
ret = -ENODEV;
|
||||
goto err_detach;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_detach:
|
||||
iommu_detach_device(cif_dev->domain, cif_dev->dev);
|
||||
err_put_cookie:
|
||||
iommu_put_dma_cookie(cif_dev->domain);
|
||||
err_free_domain:
|
||||
iommu_domain_free(cif_dev->domain);
|
||||
|
||||
dev_err(cif_dev->dev, "Failed to setup IOMMU, ret(%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rkcif_iommu_cleanup(struct rkcif_device *cif_dev)
|
||||
{
|
||||
iommu_detach_device(cif_dev->domain, cif_dev->dev);
|
||||
iommu_put_dma_cookie(cif_dev->domain);
|
||||
iommu_domain_free(cif_dev->domain);
|
||||
}
|
||||
|
||||
static inline bool is_iommu_enable(struct device *dev)
|
||||
{
|
||||
struct device_node *iommu;
|
||||
@@ -746,7 +803,6 @@ static int rkcif_plat_probe(struct platform_device *pdev)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
media_device_init(&cif_dev->media_dev);
|
||||
ret = media_device_register(&cif_dev->media_dev);
|
||||
if (ret < 0) {
|
||||
v4l2_err(v4l2_dev, "Failed to register media device: %d\n",
|
||||
@@ -760,7 +816,9 @@ static int rkcif_plat_probe(struct platform_device *pdev)
|
||||
goto err_unreg_media_dev;
|
||||
|
||||
cif_dev->iommu_en = is_iommu_enable(dev);
|
||||
if (!(cif_dev->iommu_en)) {
|
||||
if (cif_dev->iommu_en) {
|
||||
rkcif_iommu_init(cif_dev);
|
||||
} else {
|
||||
ret = of_reserved_mem_device_init(dev);
|
||||
if (ret)
|
||||
v4l2_warn(v4l2_dev,
|
||||
@@ -790,6 +848,8 @@ static int rkcif_plat_remove(struct platform_device *pdev)
|
||||
struct rkcif_device *cif_dev = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (cif_dev->iommu_en)
|
||||
rkcif_iommu_cleanup(cif_dev);
|
||||
|
||||
media_device_unregister(&cif_dev->media_dev);
|
||||
v4l2_device_unregister(&cif_dev->v4l2_dev);
|
||||
|
||||
Reference in New Issue
Block a user