Skip to content

exynos-drm and fimc/mfc fixes #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions drivers/gpu/arm/ump/common/ump_kernel_ref_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#define UMP_ADDR_ALIGN_OFFSET(x) ((x)&(UMP_MINIMUM_SIZE-1))
static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor);

UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks)
UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks2(ump_dd_physical_block * blocks, unsigned long num_blocks, int is_cached)
{
ump_dd_mem * mem;
unsigned long size_total = 0;
Expand Down Expand Up @@ -93,8 +93,7 @@ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd
mem->backend_info = NULL;
mem->ctx = NULL;
mem->release_func = phys_blocks_release;
/* For now UMP handles created by ump_dd_handle_create_from_phys_blocks() is forced to be Uncached */
mem->is_cached = 0;
mem->is_cached = is_cached;
mem->hw_device = _UMP_UK_USED_BY_CPU;
mem->lock_usage = UMP_NOT_LOCKED;

Expand All @@ -104,6 +103,12 @@ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd
return (ump_dd_handle)mem;
}

UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks)
{
/* For now UMP handles created by ump_dd_handle_create_from_phys_blocks() is forced to be Uncached */
return ump_dd_handle_create_from_phys_blocks2(blocks, num_blocks, 0);
}

static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor)
{
_mali_osk_free(descriptor->block_array);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/arm/ump/include/ump_kernel_interface_ref_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ extern "C" {

/** Turn specified physical memory into UMP memory. */
UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks);
UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks2(ump_dd_physical_block * blocks, unsigned long num_blocks, int is_cached);

#ifdef __cplusplus
}
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/arm/ump/linux/ump_kernel_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ EXPORT_SYMBOL(ump_dd_reference_release);

/* Export our own extended kernel space allocator */
EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks);
EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks2);

/* Setup init and exit functions for this module */
module_init(ump_initialize_module);
Expand Down
18 changes: 18 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <drm/drmP.h>
#include <drm/exynos_drm.h>
#include <ump/ump_kernel_interface_ref_drv.h>

#include "exynos_drm_drv.h"
#include "exynos_drm_gem.h"
Expand Down Expand Up @@ -194,6 +195,23 @@ int exynos_drm_alloc_buf(struct drm_device *dev,
void exynos_drm_free_buf(struct drm_device *dev,
unsigned int flags, struct exynos_drm_gem_buf *buffer)
{
if (buffer->ump_handle)
ump_dd_reference_release(buffer->ump_handle);

lowlevel_buffer_deallocate(dev, flags, buffer);
}

ump_dd_handle exynos_drm_get_ump_handle(struct exynos_drm_gem_buf *buffer)
{
ump_dd_physical_block ump_mem;
int is_cached;

if (buffer->ump_handle)
return buffer->ump_handle;

ump_mem.addr = buffer->dma_addr;
ump_mem.size = buffer->size;
is_cached = dma_get_attr(DMA_ATTR_NON_CONSISTENT, &buffer->dma_attrs);
buffer->ump_handle = ump_dd_handle_create_from_phys_blocks2(&ump_mem, 1, is_cached);
return buffer->ump_handle;
}
1 change: 1 addition & 0 deletions drivers/gpu/drm/exynos/exynos_drm_buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ void exynos_drm_free_buf(struct drm_device *dev,
unsigned int flags,
struct exynos_drm_gem_buf *buffer);

ump_dd_handle exynos_drm_get_ump_handle(struct exynos_drm_gem_buf *buffer);
#endif
24 changes: 12 additions & 12 deletions drivers/gpu/drm/exynos/exynos_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,17 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,

DRM_DEBUG_KMS("%s\n", __FILE__);

/* when the page flip is requested, crtc's dpms should be on */
/* if the CRTC is off, just save the new framebuffer address for use if
* we get turned on again later, and report to userspace that the flip
* completed. */
if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
DRM_ERROR("failed page flip request.\n");
return -EINVAL;
crtc->fb = fb;
if (event) {
spin_lock_irq(&dev->event_lock);
drm_send_vblank_event(dev, -1, event);
spin_unlock_irq(&dev->event_lock);
}
return 0;
}

mutex_lock(&dev->struct_mutex);
Expand All @@ -226,7 +233,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
ret = drm_vblank_get(dev, exynos_crtc->pipe);
if (ret) {
DRM_DEBUG("failed to acquire vblank counter\n");
list_del(&event->base.link);

goto out;
}
Expand Down Expand Up @@ -410,7 +416,6 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
{
struct exynos_drm_private *dev_priv = dev->dev_private;
struct drm_pending_vblank_event *e, *t;
struct timeval now;
struct drm_crtc *drm_crtc = dev_priv->crtc[crtc];
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
unsigned long flags;
Expand All @@ -425,13 +430,8 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
if (crtc != e->pipe)
continue;

do_gettimeofday(&now);
e->event.sequence = 0;
e->event.tv_sec = now.tv_sec;
e->event.tv_usec = now.tv_usec;

list_move_tail(&e->base.link, &e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
list_del(&e->base.link);
drm_send_vblank_event(dev, -1, e);
drm_vblank_put(dev, crtc);
atomic_set(&exynos_crtc->pending_flip, 0);
wake_up(&exynos_crtc->pending_flip_queue);
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
static struct drm_ioctl_desc exynos_ioctls[] = {
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
DRM_UNLOCKED | DRM_AUTH),
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE2, exynos_drm_gem_create2_ioctl,
DRM_UNLOCKED | DRM_AUTH),
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET,
exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED |
DRM_AUTH),
Expand Down
31 changes: 31 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <linux/shmem_fs.h>
#include <drm/exynos_drm.h>
#include <ump/ump_kernel_interface_ref_drv.h>

#include "exynos_drm_drv.h"
#include "exynos_drm_gem.h"
Expand Down Expand Up @@ -263,6 +264,36 @@ int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
return 0;
}

int exynos_drm_gem_create2_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_exynos_gem_create2 *args = data;
struct exynos_drm_gem_obj *exynos_gem_obj;
ump_dd_handle ump_handle;
int ret;

DRM_DEBUG_KMS("%s\n", __FILE__);

exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);
if (IS_ERR(exynos_gem_obj))
return PTR_ERR(exynos_gem_obj);

ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
&args->handle);
if (ret) {
exynos_drm_gem_destroy(exynos_gem_obj);
return ret;
}

ump_handle = exynos_drm_get_ump_handle(exynos_gem_obj->buffer);
if (ump_handle != UMP_DD_HANDLE_INVALID)
args->name = ump_dd_secure_id_get(ump_handle);
else
args->name = 0;

return 0;
}

dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
unsigned int gem_handle,
struct drm_file *filp)
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_gem.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#ifndef _EXYNOS_DRM_GEM_H_
#define _EXYNOS_DRM_GEM_H_
#include <ump/ump_kernel_interface_ref_drv.h>

#define to_exynos_gem_obj(x) container_of(x,\
struct exynos_drm_gem_obj, base)
Expand Down Expand Up @@ -40,6 +41,7 @@ struct exynos_drm_gem_buf {
unsigned int write;
struct page **pages;
struct sg_table *sgt;
ump_dd_handle ump_handle;
unsigned long size;
bool pfnmap;
};
Expand Down Expand Up @@ -92,6 +94,8 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
*/
int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int exynos_drm_gem_create2_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);

/*
* get dma address from gem handle and this function could be used for
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/exynos/exynos_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,11 @@ static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
(check_timing->vmode & FB_VMODE_INTERLACED) ?
true : false);

/* 800x600 is displayed badly like 1024x768, but I can't find a timing
* hack to make it look OK. */
if (check_timing->xres == 800 && check_timing->yres == 600)
return -EINVAL;

for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++)
if (hdmiphy_v14_configs[i].pixel_clock ==
check_timing->pixclock)
Expand Down
41 changes: 26 additions & 15 deletions drivers/media/platform/s5p-fimc/fimc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ static struct fimc_fmt fimc_formats[] = {
.colplanes = 1,
.flags = FMT_FLAGS_M2M,
}, {
.name = "ARGB8888, 32 bpp",
.fourcc = V4L2_PIX_FMT_RGB32,
.name = "BGRA8888, 32 bpp",
.fourcc = V4L2_PIX_FMT_BGR32,
.depth = { 32 },
.color = FIMC_FMT_RGB888,
.memplanes = 1,
Expand Down Expand Up @@ -118,7 +118,7 @@ static struct fimc_fmt fimc_formats[] = {
}, {
.name = "YUV 4:2:2 planar, Y/Cb/Cr",
.fourcc = V4L2_PIX_FMT_YUV422P,
.depth = { 12 },
.depth = { 16 },
.color = FIMC_FMT_YCBYCR422,
.memplanes = 1,
.colplanes = 3,
Expand Down Expand Up @@ -446,7 +446,7 @@ void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
struct fimc_variant *variant = ctx->fimc_dev->variant;
u32 i, depth = 0;

for (i = 0; i < f->fmt->colplanes; i++)
for (i = 0; i < f->fmt->memplanes; i++)
depth += f->fmt->depth[i];

f->dma_offset.y_h = f->offs_h;
Expand Down Expand Up @@ -712,13 +712,8 @@ int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f)
bpl = (bpl * frame->fmt->depth[0]) / 8;
pixm->plane_fmt[i].bytesperline = bpl;

if (frame->fmt->flags & FMT_FLAGS_COMPRESSED) {
pixm->plane_fmt[i].sizeimage = frame->payload[i];
continue;
}
pixm->plane_fmt[i].sizeimage = (frame->o_width *
frame->o_height * frame->fmt->depth[i]) / 8;
}
pixm->plane_fmt[i].sizeimage = frame->payload[i];
}
return 0;
}

Expand Down Expand Up @@ -761,20 +756,36 @@ void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
for (i = 0; i < pix->num_planes; ++i) {
struct v4l2_plane_pix_format *plane_fmt = &pix->plane_fmt[i];
u32 bpl = plane_fmt->bytesperline;
u32 sizeimage;

if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
bpl = pix->width; /* Planar */

if (fmt->colplanes == 1 && /* Packed */
(bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
bpl = (pix->width * fmt->depth[0]) / 8;

if (i == 0) /* Same bytesperline for each plane. */
/*
* Currently bytesperline for each plane is same, except
* V4L2_PIX_FMT_YUV420M format. This calculation may need
* to be changed when other multi-planar formats are added
* to the fimc_formats[] array.
*/
if (i == 0)
bytesperline = bpl;
else if (i == 1 && fmt->memplanes == 3)
bytesperline /= 2;

plane_fmt->bytesperline = bytesperline;
plane_fmt->sizeimage = max((pix->width * pix->height *
fmt->depth[i]) / 8, plane_fmt->sizeimage);
sizeimage = pix->width * pix->height * fmt->depth[i] / 8;

/* Ensure full row for tiled formats */
if (tiled_fmt(fmt)) {
/* 64 * 32 * plane_fmt->bytesperline / 64 */
u32 row_size = plane_fmt->bytesperline * 32;
sizeimage = roundup(sizeimage, row_size);
}

plane_fmt->sizeimage = max(sizeimage, plane_fmt->sizeimage);
}
}

Expand Down
10 changes: 5 additions & 5 deletions drivers/media/platform/s5p-fimc/fimc-m2m.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,

*num_planes = f->fmt->memplanes;
for (i = 0; i < f->fmt->memplanes; i++) {
sizes[i] = (f->f_width * f->f_height * f->fmt->depth[i]) / 8;
sizes[i] = f->payload[i];
allocators[i] = ctx->fimc_dev->alloc_ctx;
}
return 0;
Expand Down Expand Up @@ -388,9 +388,9 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
/* Update RGB Alpha control state and value range */
fimc_alpha_ctrl_update(ctx);

for (i = 0; i < frame->fmt->colplanes; i++) {
frame->payload[i] =
(pix->width * pix->height * frame->fmt->depth[i]) / 8;
for (i = 0; i < frame->fmt->memplanes; i++) {
struct v4l2_plane_pix_format *plane_fmt = &pix->plane_fmt[i];
frame->payload[i] = plane_fmt->sizeimage;
}

fimc_fill_frame(frame, f);
Expand Down Expand Up @@ -536,7 +536,7 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
else
halign = ffs(fimc->variant->min_vsize_align) - 1;

for (i = 0; i < f->fmt->colplanes; i++)
for (i = 0; i < f->fmt->memplanes; i++)
depth += f->fmt->depth[i];

v4l_bound_align_image(&cr->c.width, min_size, f->o_width,
Expand Down
31 changes: 28 additions & 3 deletions drivers/media/v4l2-core/v4l2-mem2mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,35 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_streamon);
int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
enum v4l2_buf_type type)
{
struct vb2_queue *vq;
struct v4l2_m2m_dev *m2m_dev;
struct v4l2_m2m_queue_ctx *q_ctx;
unsigned long flags_job, flags;
int ret;

vq = v4l2_m2m_get_vq(m2m_ctx, type);
return vb2_streamoff(vq, type);
q_ctx = get_queue_ctx(m2m_ctx, type);
ret = vb2_streamoff(&q_ctx->q, type);
if (ret)
return ret;

m2m_dev = m2m_ctx->m2m_dev;
spin_lock_irqsave(&m2m_dev->job_spinlock, flags_job);
/* We should not be scheduled anymore, since we're dropping a queue. */
INIT_LIST_HEAD(&m2m_ctx->queue);
m2m_ctx->job_flags = 0;

spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
/* Drop queue, since streamoff returns device to the same state as after
* calling reqbufs. */
INIT_LIST_HEAD(&q_ctx->rdy_queue);
spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);

if (m2m_dev->curr_ctx == m2m_ctx) {
m2m_dev->curr_ctx = NULL;
wake_up(&m2m_ctx->finished);
}
spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);

return 0;
}
EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff);

Expand Down
Loading