msm: jpeg: DMA V4L2 driver changes
Fixed issues in jpeg DMA v4l2 driver, related to incorrect clock index, incorrect buffer offset, incorrect dtsi node names for VBIF, QOS and mmu prefetch. CRs-Fixed: 1001324 Change-Id: Ice15afd63e006401a469376277b50a129ef177b4 Signed-off-by: Ashwini Rao <ashwinik@codeaurora.org>
This commit is contained in:
parent
f4515051a9
commit
a302531f3e
5 changed files with 180 additions and 58 deletions
|
@ -19,13 +19,18 @@ Required properties:
|
||||||
- clocks : clocks required for the device.
|
- clocks : clocks required for the device.
|
||||||
- qcom,clock-rates: should specify clock rates in Hz to each clocks
|
- qcom,clock-rates: should specify clock rates in Hz to each clocks
|
||||||
property defined.
|
property defined.
|
||||||
|
- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
|
||||||
|
below optional properties:
|
||||||
|
- qcom,msm-bus,name
|
||||||
|
- qcom,msm-bus,num-cases
|
||||||
|
- qcom,msm-bus,num-paths
|
||||||
|
- qcom,msm-bus,vectors-KBps
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- qcom,qos-regs: relative address offsets of QoS registers.
|
- qcom,vbif-reg-settings: relative address offsets and value pairs for VBIF registers.
|
||||||
- qcom,qos-settings: QoS values to be written to QoS registers.
|
- qcom,qos-reg-settings: relative address offsets and value pairs for QoS registers.
|
||||||
- qcom,vbif-regs: relative address offsets of VBIF registers.
|
- qcom,prefetch-reg-settings: relative address offsets and value pairs for
|
||||||
- qcom,vbif-settings: VBIF values to be written to VBIF registers.
|
MMU prefetch registers.
|
||||||
- qcom,prefetch-regs: relative address offsets of MMU prefetch registers.
|
|
||||||
- qcom,prefetch-settings: values to be written to MMU Prefetch registers.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
qcom,jpegdma@aa0000 {
|
qcom,jpegdma@aa0000 {
|
||||||
|
@ -53,10 +58,14 @@ Example:
|
||||||
<&clock_gcc clk_mmssnoc_axi_clk>,
|
<&clock_gcc clk_mmssnoc_axi_clk>,
|
||||||
<&clock_mmss clk_mmagic_camss_axi_clk>;
|
<&clock_mmss clk_mmagic_camss_axi_clk>;
|
||||||
qcom,clock-rates = <266670000 0 0 0 0 0 0 0 0>,
|
qcom,clock-rates = <266670000 0 0 0 0 0 0 0 0>,
|
||||||
<400000000 0 0 0 0 0 0 0 0>;
|
qcom,vbif-reg-settings = <0x4 0x1>;
|
||||||
qcom,vbif-regs = <0x4 0xDC 0x124 0x160>;
|
qcom,prefetch-reg-settings = <0x18c 0x11>,
|
||||||
qcom,vbif-settings = <0x1 0x7 0x1 0x22222222>;
|
<0x1a0 0x31>,
|
||||||
qcom,prefetch-regs = <0x18C 0x1A0 0x1B0>;
|
<0x1b0 0x31>;
|
||||||
qcom,prefetch-settings = <0x11 0x31 0x31>;
|
qcom,msm-bus,name = "msm_camera_jpeg_dma";
|
||||||
|
qcom,msm-bus,num-cases = <2>;
|
||||||
|
qcom,msm-bus,num-paths = <1>;
|
||||||
|
qcom,msm-bus,vectors-KBps = <62 512 0 0>,
|
||||||
|
<62 512 666675 666675>;
|
||||||
status = "ok";
|
status = "ok";
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include <linux/ion.h>
|
#include <linux/ion.h>
|
||||||
#include <linux/msm_ion.h>
|
#include <linux/msm_ion.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/compat.h>
|
||||||
#include <media/v4l2-ioctl.h>
|
#include <media/v4l2-ioctl.h>
|
||||||
#include <media/v4l2-event.h>
|
#include <media/v4l2-event.h>
|
||||||
#include <media/videobuf2-core.h>
|
#include <media/videobuf2-core.h>
|
||||||
|
@ -70,18 +72,31 @@ static struct msm_jpegdma_format formats[] = {
|
||||||
.planes[1] = JPEGDMA_PLANE_TYPE_CBCR,
|
.planes[1] = JPEGDMA_PLANE_TYPE_CBCR,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "YUV 4:2:0 planar, YCbCr",
|
.name = "YVU 4:2:0 planar, YCrCb",
|
||||||
.fourcc = V4L2_PIX_FMT_YUV420,
|
.fourcc = V4L2_PIX_FMT_YVU420,
|
||||||
.depth = 12,
|
.depth = 12,
|
||||||
.num_planes = 3,
|
.num_planes = 3,
|
||||||
.colplane_h = 2,
|
.colplane_h = 1,
|
||||||
.colplane_v = 2,
|
.colplane_v = 4,
|
||||||
.h_align = 2,
|
.h_align = 2,
|
||||||
.v_align = 2,
|
.v_align = 2,
|
||||||
.planes[0] = JPEGDMA_PLANE_TYPE_Y,
|
.planes[0] = JPEGDMA_PLANE_TYPE_Y,
|
||||||
.planes[1] = JPEGDMA_PLANE_TYPE_CR,
|
.planes[1] = JPEGDMA_PLANE_TYPE_CR,
|
||||||
.planes[2] = JPEGDMA_PLANE_TYPE_CB,
|
.planes[2] = JPEGDMA_PLANE_TYPE_CB,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "YUV 4:2:0 planar, YCbCr",
|
||||||
|
.fourcc = V4L2_PIX_FMT_YUV420,
|
||||||
|
.depth = 12,
|
||||||
|
.num_planes = 3,
|
||||||
|
.colplane_h = 1,
|
||||||
|
.colplane_v = 4,
|
||||||
|
.h_align = 2,
|
||||||
|
.v_align = 2,
|
||||||
|
.planes[0] = JPEGDMA_PLANE_TYPE_Y,
|
||||||
|
.planes[1] = JPEGDMA_PLANE_TYPE_CB,
|
||||||
|
.planes[2] = JPEGDMA_PLANE_TYPE_CR,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -196,7 +211,8 @@ static void msm_jpegdma_align_format(struct v4l2_format *f, int format_idx)
|
||||||
if (formats[format_idx].num_planes > 1)
|
if (formats[format_idx].num_planes > 1)
|
||||||
for (i = 1; i < formats[format_idx].num_planes; i++)
|
for (i = 1; i < formats[format_idx].num_planes; i++)
|
||||||
size_image += (f->fmt.pix.bytesperline *
|
size_image += (f->fmt.pix.bytesperline *
|
||||||
(f->fmt.pix.height / formats[format_idx].colplane_v));
|
(f->fmt.pix.height /
|
||||||
|
formats[format_idx].colplane_v));
|
||||||
|
|
||||||
f->fmt.pix.sizeimage = size_image;
|
f->fmt.pix.sizeimage = size_image;
|
||||||
f->fmt.pix.field = V4L2_FIELD_NONE;
|
f->fmt.pix.field = V4L2_FIELD_NONE;
|
||||||
|
@ -250,6 +266,9 @@ static int msm_jpegdma_update_hw_config(struct jpegdma_ctx *ctx)
|
||||||
size.fps = ctx->timeperframe.denominator /
|
size.fps = ctx->timeperframe.denominator /
|
||||||
ctx->timeperframe.numerator;
|
ctx->timeperframe.numerator;
|
||||||
|
|
||||||
|
size.in_offset = ctx->in_offset;
|
||||||
|
size.out_offset = ctx->out_offset;
|
||||||
|
|
||||||
size.format = formats[ctx->format_idx];
|
size.format = formats[ctx->format_idx];
|
||||||
|
|
||||||
msm_jpegdma_fill_size_from_ctx(ctx, &size);
|
msm_jpegdma_fill_size_from_ctx(ctx, &size);
|
||||||
|
@ -364,7 +383,9 @@ static void msm_jpegdma_stop_streaming(struct vb2_queue *q)
|
||||||
dev_err(ctx->jdma_device->dev, "Ctx wait timeout\n");
|
dev_err(ctx->jdma_device->dev, "Ctx wait timeout\n");
|
||||||
ret = -ETIME;
|
ret = -ETIME;
|
||||||
}
|
}
|
||||||
msm_jpegdma_hw_put(ctx->jdma_device);
|
|
||||||
|
if (ctx->jdma_device->ref_count > 0)
|
||||||
|
msm_jpegdma_hw_put(ctx->jdma_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Videobuf2 queue callbacks. */
|
/* Videobuf2 queue callbacks. */
|
||||||
|
@ -388,13 +409,29 @@ static void *msm_jpegdma_get_userptr(void *alloc_ctx,
|
||||||
{
|
{
|
||||||
struct msm_jpegdma_device *dma = alloc_ctx;
|
struct msm_jpegdma_device *dma = alloc_ctx;
|
||||||
struct msm_jpegdma_buf_handle *buf;
|
struct msm_jpegdma_buf_handle *buf;
|
||||||
|
struct msm_jpeg_dma_buff __user *up_buff = compat_ptr(vaddr);
|
||||||
|
struct msm_jpeg_dma_buff kp_buff;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!access_ok(VERIFY_READ, up_buff,
|
||||||
|
sizeof(struct msm_jpeg_dma_buff)) ||
|
||||||
|
get_user(kp_buff.fd, &up_buff->fd)) {
|
||||||
|
dev_err(dma->dev, "Error getting user data\n");
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!access_ok(VERIFY_WRITE, up_buff,
|
||||||
|
sizeof(struct msm_jpeg_dma_buff)) ||
|
||||||
|
put_user(kp_buff.fd, &up_buff->fd)) {
|
||||||
|
dev_err(dma->dev, "Error putting user data\n");
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
buf = kzalloc(sizeof(*buf), GFP_KERNEL);
|
buf = kzalloc(sizeof(*buf), GFP_KERNEL);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
ret = msm_jpegdma_hw_map_buffer(dma, vaddr, buf);
|
ret = msm_jpegdma_hw_map_buffer(dma, kp_buff.fd, buf);
|
||||||
if (ret < 0 || buf->size < size)
|
if (ret < 0 || buf->size < size)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -482,7 +519,6 @@ static int msm_jpegdma_open(struct file *file)
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
mutex_init(&ctx->lock);
|
|
||||||
ctx->jdma_device = device;
|
ctx->jdma_device = device;
|
||||||
dev_dbg(ctx->jdma_device->dev, "Jpeg v4l2 dma open\n");
|
dev_dbg(ctx->jdma_device->dev, "Jpeg v4l2 dma open\n");
|
||||||
/* Set ctx defaults */
|
/* Set ctx defaults */
|
||||||
|
@ -531,7 +567,9 @@ static int msm_jpegdma_release(struct file *file)
|
||||||
struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(file->private_data);
|
struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(file->private_data);
|
||||||
|
|
||||||
/* release all the resources */
|
/* release all the resources */
|
||||||
msm_jpegdma_hw_put(ctx->jdma_device);
|
if (ctx->jdma_device->ref_count > 0)
|
||||||
|
msm_jpegdma_hw_put(ctx->jdma_device);
|
||||||
|
|
||||||
atomic_set(&ctx->active, 0);
|
atomic_set(&ctx->active, 0);
|
||||||
complete_all(&ctx->completion);
|
complete_all(&ctx->completion);
|
||||||
v4l2_m2m_ctx_release(ctx->m2m_ctx);
|
v4l2_m2m_ctx_release(ctx->m2m_ctx);
|
||||||
|
@ -774,16 +812,46 @@ static int msm_jpegdma_qbuf(struct file *file, void *fh,
|
||||||
struct v4l2_buffer *buf)
|
struct v4l2_buffer *buf)
|
||||||
{
|
{
|
||||||
struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh);
|
struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh);
|
||||||
|
struct msm_jpeg_dma_buff __user *up_buff = compat_ptr(buf->m.userptr);
|
||||||
|
struct msm_jpeg_dma_buff kp_buff;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&ctx->lock);
|
if (!access_ok(VERIFY_READ, up_buff,
|
||||||
|
sizeof(struct msm_jpeg_dma_buff)) ||
|
||||||
|
get_user(kp_buff.fd, &up_buff->fd) ||
|
||||||
|
get_user(kp_buff.offset, &up_buff->offset)) {
|
||||||
|
dev_err(ctx->jdma_device->dev, "Error getting user data\n");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!access_ok(VERIFY_WRITE, up_buff,
|
||||||
|
sizeof(struct msm_jpeg_dma_buff)) ||
|
||||||
|
put_user(kp_buff.fd, &up_buff->fd) ||
|
||||||
|
put_user(kp_buff.offset, &up_buff->offset)) {
|
||||||
|
dev_err(ctx->jdma_device->dev, "Error putting user data\n");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (buf->type) {
|
||||||
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
||||||
|
ctx->in_offset = kp_buff.offset;
|
||||||
|
dev_dbg(ctx->jdma_device->dev, "input buf offset %d\n",
|
||||||
|
ctx->in_offset);
|
||||||
|
break;
|
||||||
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||||
|
ctx->out_offset = kp_buff.offset;
|
||||||
|
dev_dbg(ctx->jdma_device->dev, "output buf offset %d\n",
|
||||||
|
ctx->out_offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atomic_read(&ctx->active))
|
||||||
|
ret = msm_jpegdma_update_hw_config(ctx);
|
||||||
|
|
||||||
ret = v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
|
ret = v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(ctx->jdma_device->dev, "QBuf fail\n");
|
dev_err(ctx->jdma_device->dev, "QBuf fail\n");
|
||||||
|
|
||||||
mutex_unlock(&ctx->lock);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,14 +884,10 @@ static int msm_jpegdma_streamon(struct file *file,
|
||||||
if (!msm_jpegdma_config_ok(ctx))
|
if (!msm_jpegdma_config_ok(ctx))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&ctx->lock);
|
|
||||||
|
|
||||||
ret = v4l2_m2m_streamon(file, ctx->m2m_ctx, buf_type);
|
ret = v4l2_m2m_streamon(file, ctx->m2m_ctx, buf_type);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(ctx->jdma_device->dev, "Stream on fail\n");
|
dev_err(ctx->jdma_device->dev, "Stream on fail\n");
|
||||||
|
|
||||||
mutex_unlock(&ctx->lock);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -954,14 +1018,10 @@ static int msm_jpegdma_s_crop(struct file *file, void *fh,
|
||||||
if (crop->c.top % formats[ctx->format_idx].v_align)
|
if (crop->c.top % formats[ctx->format_idx].v_align)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&ctx->lock);
|
|
||||||
|
|
||||||
ctx->crop = crop->c;
|
ctx->crop = crop->c;
|
||||||
if (atomic_read(&ctx->active))
|
if (atomic_read(&ctx->active))
|
||||||
ret = msm_jpegdma_update_hw_config(ctx);
|
ret = msm_jpegdma_update_hw_config(ctx);
|
||||||
|
|
||||||
mutex_unlock(&ctx->lock);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1004,7 +1064,7 @@ static int msm_jpegdma_s_parm(struct file *file, void *fh,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!a->parm.output.timeperframe.numerator ||
|
if (!a->parm.output.timeperframe.numerator ||
|
||||||
!a->parm.output.timeperframe.denominator)
|
!a->parm.output.timeperframe.denominator)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Frame rate is not supported during streaming */
|
/* Frame rate is not supported during streaming */
|
||||||
|
@ -1138,16 +1198,15 @@ void msm_jpegdma_isr_processing_done(struct msm_jpegdma_device *dma)
|
||||||
struct jpegdma_ctx *ctx;
|
struct jpegdma_ctx *ctx;
|
||||||
|
|
||||||
mutex_lock(&dma->lock);
|
mutex_lock(&dma->lock);
|
||||||
|
|
||||||
ctx = v4l2_m2m_get_curr_priv(dma->m2m_dev);
|
ctx = v4l2_m2m_get_curr_priv(dma->m2m_dev);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
mutex_lock(&ctx->lock);
|
|
||||||
ctx->plane_idx++;
|
ctx->plane_idx++;
|
||||||
if (ctx->plane_idx >= formats[ctx->format_idx].num_planes) {
|
if (ctx->plane_idx >= formats[ctx->format_idx].num_planes) {
|
||||||
src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
|
src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
|
||||||
dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
|
dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
|
||||||
if (src_buf == NULL || dst_buf == NULL) {
|
if (src_buf == NULL || dst_buf == NULL) {
|
||||||
dev_err(ctx->jdma_device->dev, "Error, buffer list empty\n");
|
dev_err(ctx->jdma_device->dev, "Error, buffer list empty\n");
|
||||||
mutex_unlock(&ctx->lock);
|
|
||||||
mutex_unlock(&dma->lock);
|
mutex_unlock(&dma->lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1163,13 +1222,11 @@ void msm_jpegdma_isr_processing_done(struct msm_jpegdma_device *dma)
|
||||||
src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
|
src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
|
||||||
if (src_buf == NULL || dst_buf == NULL) {
|
if (src_buf == NULL || dst_buf == NULL) {
|
||||||
dev_err(ctx->jdma_device->dev, "Error, buffer list empty\n");
|
dev_err(ctx->jdma_device->dev, "Error, buffer list empty\n");
|
||||||
mutex_unlock(&ctx->lock);
|
|
||||||
mutex_unlock(&dma->lock);
|
mutex_unlock(&dma->lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
msm_jpegdma_process_buffers(ctx, src_buf, dst_buf);
|
msm_jpegdma_process_buffers(ctx, src_buf, dst_buf);
|
||||||
}
|
}
|
||||||
mutex_unlock(&ctx->lock);
|
|
||||||
}
|
}
|
||||||
mutex_unlock(&dma->lock);
|
mutex_unlock(&dma->lock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
/* Max number of clocks defined in device tree */
|
/* Max number of clocks defined in device tree */
|
||||||
#define MSM_JPEGDMA_MAX_CLK 10
|
#define MSM_JPEGDMA_MAX_CLK 10
|
||||||
/* Core clock index */
|
/* Core clock index */
|
||||||
#define MSM_JPEGDMA_CORE_CLK 0
|
#define MSM_JPEGDMA_CORE_CLK "core_clk"
|
||||||
/* Max number of regulators defined in device tree */
|
/* Max number of regulators defined in device tree */
|
||||||
#define MSM_JPEGDMA_MAX_REGULATOR_NUM 3
|
#define MSM_JPEGDMA_MAX_REGULATOR_NUM 3
|
||||||
/* Max number of planes supported */
|
/* Max number of planes supported */
|
||||||
|
@ -109,6 +109,8 @@ struct msm_jpegdma_size_config {
|
||||||
struct msm_jpegdma_size out_size;
|
struct msm_jpegdma_size out_size;
|
||||||
struct msm_jpegdma_format format;
|
struct msm_jpegdma_format format;
|
||||||
unsigned int fps;
|
unsigned int fps;
|
||||||
|
unsigned int in_offset;
|
||||||
|
unsigned int out_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -252,7 +254,6 @@ struct msm_jpegdma_buf_handle {
|
||||||
* @format_idx: Current format index.
|
* @format_idx: Current format index.
|
||||||
*/
|
*/
|
||||||
struct jpegdma_ctx {
|
struct jpegdma_ctx {
|
||||||
struct mutex lock;
|
|
||||||
struct msm_jpegdma_device *jdma_device;
|
struct msm_jpegdma_device *jdma_device;
|
||||||
atomic_t active;
|
atomic_t active;
|
||||||
struct completion completion;
|
struct completion completion;
|
||||||
|
@ -262,6 +263,8 @@ struct jpegdma_ctx {
|
||||||
struct v4l2_format format_out;
|
struct v4l2_format format_out;
|
||||||
struct v4l2_rect crop;
|
struct v4l2_rect crop;
|
||||||
struct v4l2_fract timeperframe;
|
struct v4l2_fract timeperframe;
|
||||||
|
unsigned int in_offset;
|
||||||
|
unsigned int out_offset;
|
||||||
|
|
||||||
unsigned int config_idx;
|
unsigned int config_idx;
|
||||||
struct msm_jpegdma_plane_config plane_config[MSM_JPEGDMA_MAX_CONFIGS];
|
struct msm_jpegdma_plane_config plane_config[MSM_JPEGDMA_MAX_CONFIGS];
|
||||||
|
|
|
@ -165,6 +165,23 @@ static int msm_jpegdma_hw_get_num_pipes(struct msm_jpegdma_device *dma)
|
||||||
return num_pipes;
|
return num_pipes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* msm_jpegdma_hw_get_clock_index - Get clock index by name
|
||||||
|
* @dma: Pointer to dma device.
|
||||||
|
* @clk_name: clock name.
|
||||||
|
*/
|
||||||
|
int msm_jpegdma_hw_get_clock_index(struct msm_jpegdma_device *dma,
|
||||||
|
const char *clk_name)
|
||||||
|
{
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < dma->num_clk; i++) {
|
||||||
|
if (!strcmp(clk_name, dma->jpeg_clk_info[i].clk_name))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* msm_jpegdma_hw_reset - Reset jpeg dma core.
|
* msm_jpegdma_hw_reset - Reset jpeg dma core.
|
||||||
* @dma: Pointer to dma device.
|
* @dma: Pointer to dma device.
|
||||||
|
@ -782,12 +799,20 @@ static int msm_jpegdma_hw_calc_speed(struct msm_jpegdma_device *dma,
|
||||||
u64 height;
|
u64 height;
|
||||||
u64 real_clock;
|
u64 real_clock;
|
||||||
u64 calc_rate;
|
u64 calc_rate;
|
||||||
|
int core_clk_idx;
|
||||||
|
|
||||||
width = size->in_size.width + size->in_size.left;
|
width = size->in_size.width + size->in_size.left;
|
||||||
height = size->in_size.height + size->in_size.top;
|
height = size->in_size.height + size->in_size.top;
|
||||||
|
|
||||||
calc_rate = (width * height * size->format.depth * size->fps) / 16;
|
calc_rate = (width * height * size->format.depth * size->fps) / 16;
|
||||||
real_clock = clk_round_rate(dma->clk[MSM_JPEGDMA_CORE_CLK], calc_rate);
|
core_clk_idx = msm_jpegdma_hw_get_clock_index(dma,
|
||||||
|
MSM_JPEGDMA_CORE_CLK);
|
||||||
|
if (core_clk_idx < 0) {
|
||||||
|
dev_err(dma->dev, "Can get clock index for dma %s\n",
|
||||||
|
MSM_JPEGDMA_CORE_CLK);
|
||||||
|
}
|
||||||
|
|
||||||
|
real_clock = clk_round_rate(dma->clk[core_clk_idx], calc_rate);
|
||||||
if (real_clock < 0) {
|
if (real_clock < 0) {
|
||||||
dev_err(dma->dev, "Can not round core clock\n");
|
dev_err(dma->dev, "Can not round core clock\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -817,6 +842,7 @@ static int msm_jpegdma_hw_set_speed(struct msm_jpegdma_device *dma,
|
||||||
struct msm_jpegdma_speed new_sp;
|
struct msm_jpegdma_speed new_sp;
|
||||||
struct msm_jpegdma_size_config new_size;
|
struct msm_jpegdma_size_config new_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
int core_clk_idx;
|
||||||
|
|
||||||
if (dma->active_clock_rate >= speed->core_clock)
|
if (dma->active_clock_rate >= speed->core_clock)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -830,7 +856,14 @@ static int msm_jpegdma_hw_set_speed(struct msm_jpegdma_device *dma,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = clk_set_rate(dma->clk[MSM_JPEGDMA_CORE_CLK], new_sp.core_clock);
|
core_clk_idx = msm_jpegdma_hw_get_clock_index(dma,
|
||||||
|
MSM_JPEGDMA_CORE_CLK);
|
||||||
|
if (core_clk_idx < 0) {
|
||||||
|
dev_err(dma->dev, "Can get clock index for dma %s\n",
|
||||||
|
MSM_JPEGDMA_CORE_CLK);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_set_rate(dma->clk[core_clk_idx], new_sp.core_clock);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dma->dev, "Fail Core clock rate %d\n", ret);
|
dev_err(dma->dev, "Fail Core clock rate %d\n", ret);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1022,13 +1055,20 @@ int msm_jpegdma_hw_set_config(struct msm_jpegdma_device *dma,
|
||||||
plane_cfg->plane[0].active_pipes = dma->hw_num_pipes;
|
plane_cfg->plane[0].active_pipes = dma->hw_num_pipes;
|
||||||
plane_cfg->plane[0].type = size_cfg->format.planes[0];
|
plane_cfg->plane[0].type = size_cfg->format.planes[0];
|
||||||
msm_jpegdma_hw_calc_config(size_cfg, &plane_cfg->plane[0]);
|
msm_jpegdma_hw_calc_config(size_cfg, &plane_cfg->plane[0]);
|
||||||
|
|
||||||
|
in_offset = size_cfg->in_offset;
|
||||||
|
out_offset = size_cfg->out_offset;
|
||||||
|
|
||||||
|
msm_jpegdma_hw_add_plane_offset(&plane_cfg->plane[0],
|
||||||
|
in_offset, out_offset);
|
||||||
|
|
||||||
if (size_cfg->format.num_planes == 1)
|
if (size_cfg->format.num_planes == 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
in_offset = size_cfg->in_size.scanline *
|
in_offset += (size_cfg->in_size.scanline *
|
||||||
size_cfg->in_size.stride;
|
size_cfg->in_size.stride);
|
||||||
out_offset = size_cfg->out_size.scanline *
|
out_offset += (size_cfg->out_size.scanline *
|
||||||
size_cfg->out_size.stride;
|
size_cfg->out_size.stride);
|
||||||
|
|
||||||
memset(&plane_size, 0x00, sizeof(plane_size));
|
memset(&plane_size, 0x00, sizeof(plane_size));
|
||||||
for (i = 1; i < size_cfg->format.num_planes; i++) {
|
for (i = 1; i < size_cfg->format.num_planes; i++) {
|
||||||
|
@ -1336,7 +1376,8 @@ int msm_jpegdma_hw_get_qos(struct msm_jpegdma_device *dma)
|
||||||
unsigned int cnt;
|
unsigned int cnt;
|
||||||
const void *property;
|
const void *property;
|
||||||
|
|
||||||
property = of_get_property(dma->dev->of_node, "qcom,qos-regs", &cnt);
|
property = of_get_property(dma->dev->of_node,
|
||||||
|
"qcom,qos-reg-settings", &cnt);
|
||||||
if (!property || !cnt) {
|
if (!property || !cnt) {
|
||||||
dev_dbg(dma->dev, "Missing qos settings\n");
|
dev_dbg(dma->dev, "Missing qos settings\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1347,9 +1388,9 @@ int msm_jpegdma_hw_get_qos(struct msm_jpegdma_device *dma)
|
||||||
if (!dma->qos_regs)
|
if (!dma->qos_regs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < cnt; i++) {
|
for (i = 0; i < cnt; i = i + 2) {
|
||||||
ret = of_property_read_u32_index(dma->dev->of_node,
|
ret = of_property_read_u32_index(dma->dev->of_node,
|
||||||
"qcom,qos-regs", i,
|
"qcom,qos-reg-settings", i,
|
||||||
&dma->qos_regs[i].reg);
|
&dma->qos_regs[i].reg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dma->dev, "can not read qos reg %d\n", i);
|
dev_err(dma->dev, "can not read qos reg %d\n", i);
|
||||||
|
@ -1357,7 +1398,7 @@ int msm_jpegdma_hw_get_qos(struct msm_jpegdma_device *dma)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = of_property_read_u32_index(dma->dev->of_node,
|
ret = of_property_read_u32_index(dma->dev->of_node,
|
||||||
"qcom,qos-settings", i,
|
"qcom,qos-reg-settings", i + 1,
|
||||||
&dma->qos_regs[i].val);
|
&dma->qos_regs[i].val);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dma->dev, "can not read qos setting %d\n", i);
|
dev_err(dma->dev, "can not read qos setting %d\n", i);
|
||||||
|
@ -1397,7 +1438,8 @@ int msm_jpegdma_hw_get_vbif(struct msm_jpegdma_device *dma)
|
||||||
unsigned int cnt;
|
unsigned int cnt;
|
||||||
const void *property;
|
const void *property;
|
||||||
|
|
||||||
property = of_get_property(dma->dev->of_node, "qcom,vbif-regs", &cnt);
|
property = of_get_property(dma->dev->of_node, "qcom,vbif-reg-settings",
|
||||||
|
&cnt);
|
||||||
if (!property || !cnt) {
|
if (!property || !cnt) {
|
||||||
dev_dbg(dma->dev, "Missing vbif settings\n");
|
dev_dbg(dma->dev, "Missing vbif settings\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1408,9 +1450,9 @@ int msm_jpegdma_hw_get_vbif(struct msm_jpegdma_device *dma)
|
||||||
if (!dma->vbif_regs)
|
if (!dma->vbif_regs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < cnt; i++) {
|
for (i = 0; i < cnt; i = i + 2) {
|
||||||
ret = of_property_read_u32_index(dma->dev->of_node,
|
ret = of_property_read_u32_index(dma->dev->of_node,
|
||||||
"qcom,vbif-regs", i,
|
"qcom,vbif-reg-settings", i,
|
||||||
&dma->vbif_regs[i].reg);
|
&dma->vbif_regs[i].reg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dma->dev, "can not read vbif reg %d\n", i);
|
dev_err(dma->dev, "can not read vbif reg %d\n", i);
|
||||||
|
@ -1418,7 +1460,7 @@ int msm_jpegdma_hw_get_vbif(struct msm_jpegdma_device *dma)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = of_property_read_u32_index(dma->dev->of_node,
|
ret = of_property_read_u32_index(dma->dev->of_node,
|
||||||
"qcom,vbif-settings", i,
|
"qcom,vbif-reg-settings", i + 1,
|
||||||
&dma->vbif_regs[i].val);
|
&dma->vbif_regs[i].val);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dma->dev, "can not read vbif setting %d\n", i);
|
dev_err(dma->dev, "can not read vbif setting %d\n", i);
|
||||||
|
@ -1459,8 +1501,8 @@ int msm_jpegdma_hw_get_prefetch(struct msm_jpegdma_device *dma)
|
||||||
unsigned int cnt;
|
unsigned int cnt;
|
||||||
const void *property;
|
const void *property;
|
||||||
|
|
||||||
property = of_get_property(dma->dev->of_node, "qcom,prefetch-regs",
|
property = of_get_property(dma->dev->of_node,
|
||||||
&cnt);
|
"qcom,prefetch-reg-settings", &cnt);
|
||||||
if (!property || !cnt) {
|
if (!property || !cnt) {
|
||||||
dev_dbg(dma->dev, "Missing prefetch settings\n");
|
dev_dbg(dma->dev, "Missing prefetch settings\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1472,9 +1514,9 @@ int msm_jpegdma_hw_get_prefetch(struct msm_jpegdma_device *dma)
|
||||||
if (!dma->prefetch_regs)
|
if (!dma->prefetch_regs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < cnt; i++) {
|
for (i = 0; i < cnt; i = i + 2) {
|
||||||
ret = of_property_read_u32_index(dma->dev->of_node,
|
ret = of_property_read_u32_index(dma->dev->of_node,
|
||||||
"qcom,prefetch-regs", i,
|
"qcom,prefetch-reg-settings", i,
|
||||||
&dma->prefetch_regs[i].reg);
|
&dma->prefetch_regs[i].reg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dma->dev, "can not read prefetch reg %d\n", i);
|
dev_err(dma->dev, "can not read prefetch reg %d\n", i);
|
||||||
|
@ -1482,7 +1524,7 @@ int msm_jpegdma_hw_get_prefetch(struct msm_jpegdma_device *dma)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = of_property_read_u32_index(dma->dev->of_node,
|
ret = of_property_read_u32_index(dma->dev->of_node,
|
||||||
"qcom,prefetch-settings", i,
|
"qcom,prefetch-reg-settings", i + 1,
|
||||||
&dma->prefetch_regs[i].val);
|
&dma->prefetch_regs[i].val);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dma->dev, "can not read prefetch setting %d\n",
|
dev_err(dma->dev, "can not read prefetch setting %d\n",
|
||||||
|
@ -1598,6 +1640,9 @@ int msm_jpegdma_hw_get(struct msm_jpegdma_device *dma)
|
||||||
msm_jpegdma_hw_config_qos(dma);
|
msm_jpegdma_hw_config_qos(dma);
|
||||||
msm_jpegdma_hw_config_vbif(dma);
|
msm_jpegdma_hw_config_vbif(dma);
|
||||||
|
|
||||||
|
msm_camera_register_threaded_irq(dma->pdev, dma->irq, NULL,
|
||||||
|
msm_jpegdma_hw_irq, IRQF_ONESHOT | IRQF_TRIGGER_RISING,
|
||||||
|
dev_name(&dma->pdev->dev), dma);
|
||||||
msm_jpegdma_hw_enable_irq(dma);
|
msm_jpegdma_hw_enable_irq(dma);
|
||||||
|
|
||||||
ret = msm_jpegdma_hw_reset(dma);
|
ret = msm_jpegdma_hw_reset(dma);
|
||||||
|
@ -1710,6 +1755,7 @@ error:
|
||||||
static void msm_jpegdma_hw_detach_iommu(struct msm_jpegdma_device *dma)
|
static void msm_jpegdma_hw_detach_iommu(struct msm_jpegdma_device *dma)
|
||||||
{
|
{
|
||||||
mutex_lock(&dma->lock);
|
mutex_lock(&dma->lock);
|
||||||
|
|
||||||
if (dma->iommu_attached_cnt == 0) {
|
if (dma->iommu_attached_cnt == 0) {
|
||||||
dev_err(dma->dev, "There is no attached device\n");
|
dev_err(dma->dev, "There is no attached device\n");
|
||||||
mutex_unlock(&dma->lock);
|
mutex_unlock(&dma->lock);
|
||||||
|
@ -1720,6 +1766,7 @@ static void msm_jpegdma_hw_detach_iommu(struct msm_jpegdma_device *dma)
|
||||||
cam_smmu_ops(dma->iommu_hndl, CAM_SMMU_DETACH);
|
cam_smmu_ops(dma->iommu_hndl, CAM_SMMU_DETACH);
|
||||||
cam_smmu_destroy_handle(dma->iommu_hndl);
|
cam_smmu_destroy_handle(dma->iommu_hndl);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&dma->lock);
|
mutex_unlock(&dma->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -18,4 +18,10 @@
|
||||||
/* msm jpeg dma control ID's */
|
/* msm jpeg dma control ID's */
|
||||||
#define V4L2_CID_JPEG_DMA_SPEED (V4L2_CID_PRIVATE_BASE)
|
#define V4L2_CID_JPEG_DMA_SPEED (V4L2_CID_PRIVATE_BASE)
|
||||||
|
|
||||||
|
/* msm_jpeg_dma_buf */
|
||||||
|
struct msm_jpeg_dma_buff {
|
||||||
|
int32_t fd;
|
||||||
|
uint32_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* __UAPI_MSM_JPEG_DMA__ */
|
#endif /* __UAPI_MSM_JPEG_DMA__ */
|
||||||
|
|
Loading…
Add table
Reference in a new issue