1520 lines
39 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* drivers/video/rockchip/video/vehicle_flinger.c
*
* Copyright (C) 2022 Rockchip Electronics Co., Ltd.
* Authors:
* Jianwei Fan <jianwei.fan@rock-chips.com>
*
*/
#include <linux/atomic.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kthread.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <asm/div64.h>
#include <linux/uaccess.h>
#include <linux/linux_logo.h>
#include <linux/dma-mapping.h>
#include <linux/regulator/consumer.h>
#include <linux/of_address.h>
#include <linux/memblock.h>
#include <linux/kthread.h>
#include <linux/fdtable.h>
#include <linux/miscdevice.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <video/of_display_timing.h>
#include <video/display_timing.h>
#endif
#include "vehicle_flinger.h"
#include "../../../gpu/drm/rockchip/rockchip_drm_direct_show.h"
#include "../drivers/video/rockchip/rga3/include/rga_drv.h"
static int vehicle_dump_cif;
static int vehicle_dump_rga;
static int vehicle_dump_vop;
enum force_value {
FORCE_WIDTH = 1920,
FORCE_HEIGHT = 1080,
FORCE_STRIDE = 1920,
FORCE_XOFFSET = 0,
FORCE_YOFFSET = 0,
FORCE_FORMAT = HAL_PIXEL_FORMAT_YCrCb_NV12,
FORCE_ROTATION = RGA_TRANSFORM_ROT_0,
};
enum {
NUM_SOURCE_BUFFERS = 5, /*5 src buffer for cif*/
NUM_TARGET_BUFFERS = 3, /*3 dst buffer rga*/
};
enum buffer_state {
UNKNOWN = 0,
FREE,
DEQUEUE,
QUEUE,
ACQUIRE,
DISPLAY,
};
struct rect {
size_t x;
size_t y;
size_t w;
size_t h;
size_t s;
size_t f;
};
struct graphic_buffer {
struct list_head list;
uint32_t handle;
struct rockchip_drm_direct_show_buffer *drm_buffer;
int fd;
struct sync_fence *rel_fence;
struct rect src;
struct rect dst;
enum buffer_state state;
unsigned long phy_addr;
void *vir_addr;
int rotation;
int offset;
int len;
int width;
int height;
int stride;
int format;
struct work_struct render_work;
ktime_t timestamp;
};
struct queue_buffer {
struct list_head list;
struct graphic_buffer *buffer;
};
struct flinger {
struct device *dev;
struct ion_client *ion_client;
struct work_struct init_work;
struct work_struct render_work;
struct workqueue_struct *render_workqueue;
struct mutex source_buffer_lock;/*src buffer lock*/
struct mutex target_buffer_lock;/*dst buffer lock*/
struct graphic_buffer source_buffer[NUM_SOURCE_BUFFERS];
struct graphic_buffer target_buffer[NUM_TARGET_BUFFERS];
struct mutex queue_buffer_lock;
struct list_head queue_buffer_list;
wait_queue_head_t worker_wait;
atomic_t worker_cond_atomic;
atomic_t worker_running_atomic;
int source_index;
int target_index;
struct vehicle_cfg v_cfg;
int cvbs_field_count;
struct graphic_buffer *last_src_buffer;
/*debug*/
int debug_cif_count;
int debug_vop_count;
bool running;
struct drm_device *drm_dev;
struct drm_crtc *crtc;
struct drm_plane *plane;
const char *crtc_name;
const char *plane_name;
};
static struct flinger *flinger;
static int rk_flinger_queue_work(struct flinger *flinger,
struct graphic_buffer *src_buffer);
static int rk_flinger_alloc_bpp(int format)
{
int width = 4;
switch (format) {
case HAL_PIXEL_FORMAT_RGB_565:
width = 2;
break;
case HAL_PIXEL_FORMAT_RGB_888:
width = 3;
break;
case HAL_PIXEL_FORMAT_RGBA_8888:
width = 4;
break;
case HAL_PIXEL_FORMAT_RGBX_8888:
width = 4;
break;
case HAL_PIXEL_FORMAT_BGRA_8888:
width = 4;
break;
case HAL_PIXEL_FORMAT_YCrCb_NV12:
width = 2;
break;
default:
VEHICLE_INFO("%s: unsupported format: 0x%x\n", __func__, format);
break;
}
return width;
}
static int rk_flinger_HAL_format_to_DRM(int format)
{
int drm_format = 0;
switch (format) {
case HAL_PIXEL_FORMAT_RGBX_8888:
drm_format = DRM_FORMAT_XRGB8888;
break;
case HAL_PIXEL_FORMAT_YCrCb_NV12:
drm_format = DRM_FORMAT_NV12;
break;
case HAL_PIXEL_FORMAT_RGB_888:
drm_format = DRM_FORMAT_RGB888;
break;
case HAL_PIXEL_FORMAT_RGB_565:
drm_format = DRM_FORMAT_RGB565;
break;
default:
VEHICLE_INFO("%s: unsupported format: 0x%x\n", __func__, format);
break;
}
return drm_format;
}
static int rk_flinger_alloc_buffer(struct flinger *flg,
struct graphic_buffer *buffer,
int w, int h,
int s, int f)
{
unsigned long phy_addr;
size_t len;
int bpp;
int ret = 0;
struct rockchip_drm_direct_show_buffer *create_buffer;
VEHICLE_DG("------------alloc buffer start---------\n");
if (!flg)
return -ENODEV;
if (!buffer)
return -EINVAL;
bpp = rk_flinger_alloc_bpp(f);
len = s * h * bpp;
create_buffer = kmalloc(sizeof(struct rockchip_drm_direct_show_buffer), GFP_KERNEL);
if (!create_buffer)
return -ENOMEM;
create_buffer->width = w;
create_buffer->height = h;
create_buffer->pixel_format = rk_flinger_HAL_format_to_DRM(f);
create_buffer->flag = ROCKCHIP_BO_CONTIG;
ret = rockchip_drm_direct_show_alloc_buffer(flg->drm_dev, create_buffer);
if (ret)
VEHICLE_DGERR("error: failed to alloc drm buffer\n");
VEHICLE_DG("-----creat buffer over-----\n");
buffer->vir_addr = create_buffer->vir_addr[0];
buffer->handle = create_buffer->dmabuf_fd;
phy_addr = create_buffer->phy_addr[0];
buffer->fd = create_buffer->dmabuf_fd;
buffer->drm_buffer = create_buffer;
buffer->rel_fence = NULL;
buffer->phy_addr = phy_addr;
buffer->rotation = 0;
buffer->width = w;
buffer->height = h;
buffer->stride = s;
buffer->format = f;
buffer->len = len;
return ret;
}
static int rk_flinger_free_buffer(struct flinger *flinger,
struct graphic_buffer *buffer)
{
if (!flinger)
return -ENODEV;
if (!buffer)
return -EINVAL;
if (buffer->drm_buffer)
rockchip_drm_direct_show_free_buffer(flinger->drm_dev,
buffer->drm_buffer);
return 0;
}
static int rk_flinger_create_worker(struct flinger *flinger)
{
struct workqueue_struct *wq = NULL;
wq = create_singlethread_workqueue("flinger-render");
if (!wq) {
VEHICLE_DGERR("wzqtest Failed to create flinger workqueue\n");
return -ENODEV;
}
flinger->render_workqueue = wq;
return 0;
}
static int rk_flinger_destroy_worker(struct flinger *flinger)
{
if (!flinger)
return -ENODEV;
if (flinger->render_workqueue)
destroy_workqueue(flinger->render_workqueue);
return 0;
}
static int vehicle_flinger_parse_dt(struct flinger *flinger)
{
struct device *dev = flinger->dev;
if (of_property_read_string(dev->of_node, "vehicle,crtc_name", &flinger->crtc_name)) {
dev_info(dev, "%s: get crtc_name failed, use default!\n", __func__);
flinger->crtc_name = "video_port3";
} else {
dev_info(dev, "%s: get crtc name from dts, crtc-name = %s\n",
__func__, flinger->crtc_name);
}
if (of_property_read_string(dev->of_node, "vehicle,plane_name", &flinger->plane_name)) {
dev_info(dev, "%s: get crtc_name failed, use default!\n", __func__);
flinger->plane_name = "Esmart3-win0";
} else {
dev_info(dev, "%s: get crtc name from dts, crtc-name = %s\n",
__func__, flinger->plane_name);
}
return 0;
}
int vehicle_flinger_init(struct device *dev, struct vehicle_cfg *v_cfg)
{
struct graphic_buffer *buffer;
struct flinger *flg = NULL;
int i, ret, w, h, s, f;
static bool inited;
if (inited)
return 0;
VEHICLE_INFO("%s: v_cfg->rotate_mirror(0x%x)\n", __func__, v_cfg->rotate_mirror);
// if (FORCE_ROTATION == RGA_TRANSFORM_ROT_270 || FORCE_ROTATION == RGA_TRANSFORM_ROT_90) {
if ((v_cfg->rotate_mirror & RGA_TRANSFORM_ROT_MASK) == 0x01 ||
(v_cfg->rotate_mirror & RGA_TRANSFORM_ROT_MASK) == 0x04) {
w = FORCE_WIDTH;
h = ALIGN(FORCE_HEIGHT, 64);
s = ALIGN(FORCE_HEIGHT, 64);
f = FORCE_FORMAT;
} else {
w = ALIGN(FORCE_WIDTH, 64);
h = FORCE_HEIGHT;
s = ALIGN(FORCE_STRIDE, 64);
f = FORCE_FORMAT;
}
flg = kzalloc(sizeof(*flg), GFP_KERNEL);
if (!flg) {
VEHICLE_DGERR("flinger is NULL\n");
return -ENOMEM;
}
if (!flg->drm_dev)
flg->drm_dev = rockchip_drm_get_dev();
if (!flg->drm_dev) {
VEHICLE_DGERR("------drm device is not ready!!!-----\n");
kfree(flg);
return -ENODEV;
}
mutex_init(&flg->queue_buffer_lock);
mutex_init(&flg->source_buffer_lock);
mutex_init(&flg->target_buffer_lock);
INIT_LIST_HEAD(&flg->queue_buffer_list);
init_waitqueue_head(&flg->worker_wait);
atomic_set(&flg->worker_cond_atomic, 0);
atomic_set(&flg->worker_running_atomic, 1);
for (i = 0; i < NUM_SOURCE_BUFFERS; i++) {
flg->source_buffer[i].handle = 0;
flg->source_buffer[i].phy_addr = 0;
flg->source_buffer[i].fd = -1;
}
for (i = 0; i < NUM_TARGET_BUFFERS; i++) {
flg->target_buffer[i].phy_addr = 0;
flg->target_buffer[i].handle = 0;
flg->target_buffer[i].fd = -1;
}
for (i = 0; i < NUM_SOURCE_BUFFERS; i++) {
buffer = &(flg->source_buffer[i]);
ret = rk_flinger_alloc_buffer(flg, buffer, w, h, s, f);
if (ret) {
VEHICLE_DGERR("rk_flinger alloc src buffer failed(%d)\n",
ret);
goto free_dst_alloc;
}
buffer->state = FREE;
}
for (i = 0; i < NUM_TARGET_BUFFERS; i++) {
buffer = &(flg->target_buffer[i]);
// f = HAL_PIXEL_FORMAT_RGBX_8888;
// if (FORCE_ROTATION == RGA_TRANSFORM_ROT_270 ||
// FORCE_ROTATION == RGA_TRANSFORM_ROT_90)
if ((v_cfg->rotate_mirror & RGA_TRANSFORM_ROT_MASK) == 0x01 ||
(v_cfg->rotate_mirror & RGA_TRANSFORM_ROT_MASK) == 0x04)
ret = rk_flinger_alloc_buffer(flg, buffer, h, w, s, f);
else
ret = rk_flinger_alloc_buffer(flg, buffer, w, h, s, f);
// ret = rk_flinger_alloc_buffer(flg, buffer, w, h, s, f);
if (ret) {
VEHICLE_DGERR("rk_flinger alloc dst buffer failed\n");
goto free_src_alloc;
}
buffer->state = FREE;
}
ret = rk_flinger_create_worker(flg);
if (ret) {
VEHICLE_DGERR("rk_flinger create worker failed\n");
goto free_dst_alloc;
}
flinger = flg;
memcpy(&flg->v_cfg, v_cfg, sizeof(struct vehicle_cfg));
rk_flinger_queue_work(flg, NULL);
flg->dev = dev;
ret = vehicle_flinger_parse_dt(flg);
if (ret) {
VEHICLE_DGERR("vehicle flinger parse dts failed\n");
goto free_dst_alloc;
}
VEHICLE_INFO("vehicle flinger init ok\n");
inited = true;
return 0;
free_dst_alloc:
for (i = 0; i < NUM_TARGET_BUFFERS; i++)
rk_flinger_free_buffer(flg, &(flg->target_buffer[i]));
free_src_alloc:
for (i = 0; i < NUM_SOURCE_BUFFERS; i++)
rk_flinger_free_buffer(flg, &(flg->source_buffer[i]));
return -EINVAL;
}
__maybe_unused int vehicle_flinger_deinit(void)
{
struct flinger *flg = flinger;
int i;
if (!flg)
return -ENODEV;
atomic_set(&flg->worker_running_atomic, 0);
atomic_inc(&flg->worker_cond_atomic);
wake_up(&flg->worker_wait);
flush_work(&flg->render_work);
flush_workqueue(flg->render_workqueue);
rk_flinger_destroy_worker(flg);
flinger = NULL;
for (i = 0; i < NUM_SOURCE_BUFFERS; i++)
rk_flinger_free_buffer(flg, &flg->source_buffer[i]);
for (i = 0; i < NUM_TARGET_BUFFERS; i++)
rk_flinger_free_buffer(flg, &flg->target_buffer[i]);
kfree(flg);
return 0;
}
static int rk_flinger_format_hal_to_rga(int format)
{
int rga_format = -1;
switch (format) {
case HAL_PIXEL_FORMAT_RGB_565:
rga_format = RGA_FORMAT_RGB_565;
break;
case HAL_PIXEL_FORMAT_RGB_888:
rga_format = RGA_FORMAT_RGB_888;
break;
case HAL_PIXEL_FORMAT_RGBA_8888:
rga_format = RGA_FORMAT_RGBA_8888;
break;
case HAL_PIXEL_FORMAT_RGBX_8888:
rga_format = RGA_FORMAT_RGBX_8888;
break;
case HAL_PIXEL_FORMAT_BGRA_8888:
rga_format = RGA_FORMAT_BGRA_8888;
break;
case HAL_PIXEL_FORMAT_YCrCb_NV12:
rga_format = RGA_FORMAT_YCrCb_420_SP;
break;
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
rga_format = RGA_FORMAT_YCbCr_422_SP;
break;
default:
break;
}
return rga_format;
}
static int rk_flinger_set_rect(struct rect *rect, int x, size_t y,
int w, int h, int s, int f)
{
if (!rect)
return -EINVAL;
rect->x = x;
rect->y = y;
rect->w = w;
rect->h = h;
rect->s = s;
rect->f = f;
return 0;
}
static int
rk_flinger_set_buffer_rotation(struct graphic_buffer *buffer, int r)
{
if (!buffer)
return -EINVAL;
buffer->rotation = r;
return buffer->rotation;
}
static int
rk_flinger_cacultae_dst_rect_by_rotation(struct graphic_buffer *buffer)
{
struct rect *src_rect, *dst_rect;
if (!buffer)
return -EINVAL;
src_rect = &buffer->src;
dst_rect = &buffer->dst;
switch (buffer->rotation & RGA_TRANSFORM_ROT_MASK) {
case RGA_TRANSFORM_ROT_90:
case RGA_TRANSFORM_ROT_270:
dst_rect->x = src_rect->x;
dst_rect->y = src_rect->y;
dst_rect->h = src_rect->w;
dst_rect->w = src_rect->h;
dst_rect->s = src_rect->h;
break;
case RGA_TRANSFORM_ROT_0:
case RGA_TRANSFORM_ROT_180:
case RGA_TRANSFORM_FLIP_H:
case RGA_TRANSFORM_FLIP_V:
default:
dst_rect->x = src_rect->x;
dst_rect->y = src_rect->y;
dst_rect->w = src_rect->w;
dst_rect->h = src_rect->h;
dst_rect->s = src_rect->s;
break;
}
return 0;
}
static int rk_flinger_fill_buffer_rects(struct graphic_buffer *buffer,
struct rect *src_rect,
struct rect *dst_rect)
{
if (!buffer)
return -EINVAL;
if (src_rect)
memcpy(&buffer->src, src_rect, sizeof(struct rect));
if (dst_rect)
memcpy(&buffer->dst, dst_rect, sizeof(struct rect));
return 0;
}
static int rk_flinger_iep_deinterlace(struct flinger *flinger,
struct graphic_buffer *src_buffer,
struct graphic_buffer *dst_buffer)
{
struct rga_req rga_request;
int ret;
memset(&rga_request, 0, sizeof(rga_request));
if (!src_buffer || !dst_buffer)
return -EINVAL;
rga_request.rotate_mode = 0;
rga_request.sina = 0;
rga_request.cosa = 0;
rga_request.src.act_w = src_buffer->src.w;
rga_request.src.act_h = src_buffer->src.h;
rga_request.src.x_offset = 0;
rga_request.src.y_offset = 0;
rga_request.src.vir_w = src_buffer->src.w;
rga_request.src.vir_h = src_buffer->src.h;
rga_request.src.yrgb_addr = src_buffer->fd;
rga_request.src.uv_addr = 0;
rga_request.src.v_addr = 0;
rga_request.src.format = RGA_FORMAT_YCrCb_420_SP;
if (src_buffer->rotation == RGA_TRANSFORM_ROT_0 ||
src_buffer->rotation == RGA_TRANSFORM_ROT_180) {
rga_request.dst.act_w = src_buffer->src.w;
rga_request.dst.act_h = src_buffer->src.h / 2;
rga_request.dst.vir_w = src_buffer->src.w;
rga_request.dst.vir_h = src_buffer->src.h / 2;
} else {
rga_request.dst.act_w = src_buffer->src.w / 2;
rga_request.dst.act_h = src_buffer->src.h;
rga_request.dst.vir_w = src_buffer->src.w / 2;
rga_request.dst.vir_h = src_buffer->src.h;
}
rga_request.dst.x_offset = 0;
rga_request.dst.y_offset = 0;
rga_request.dst.yrgb_addr = dst_buffer->fd;
rga_request.dst.uv_addr = 0;
rga_request.dst.v_addr = 0;
rga_request.dst.format = RGA_FORMAT_YCrCb_420_SP;
rga_request.scale_mode = 1;
rga_request.mmu_info.mmu_en = 1;
rga_request.mmu_info.mmu_flag = ((2 & 0x3) << 4) |
1 | (1 << 31 | 1 << 8 | 1 << 10);
rga_request.src.rd_mode = RGA_RASTER_MODE;
rga_request.dst.rd_mode = RGA_RASTER_MODE;
ret = rga_kernel_commit(&rga_request);
if (ret)
VEHICLE_DGERR("RGA_BLIT_SYNC failed(%d)\n", ret);
dst_buffer->width = src_buffer->width;
dst_buffer->height = src_buffer->height;
dst_buffer->src.f = src_buffer->src.f;
if (src_buffer->rotation == RGA_TRANSFORM_ROT_0 ||
src_buffer->rotation == RGA_TRANSFORM_ROT_180) {
dst_buffer->src.w = src_buffer->src.w;
dst_buffer->src.h = src_buffer->src.h / 2;
} else {
dst_buffer->src.w = src_buffer->src.w / 2;
dst_buffer->src.h = src_buffer->src.h;
}
dst_buffer->src.x = 0;
dst_buffer->src.y = 0;
src_buffer->state = FREE;
return 0;
}
static int rk_flinger_rga_scaler(struct flinger *flinger,
struct graphic_buffer *src_buffer,
struct graphic_buffer *dst_buffer)
{
struct rga_req rga_request;
int ret;
memset(&rga_request, 0, sizeof(rga_request));
if (!src_buffer || !dst_buffer)
return -EINVAL;
rga_request.rotate_mode = 0;
rga_request.sina = 0;
rga_request.cosa = 0;
rga_request.yuv2rgb_mode = 0x0 << 0; // yuvtoyuv config 0
/* yuv to rgb color space transform if need */
//rga_request.yuv2rgb_mode = 0x1 << 0; // limit range
//rga_request.yuv2rgb_mode = 0x2 << 0; // full range
rga_request.src.act_w = src_buffer->src.w;
rga_request.src.act_h = src_buffer->src.h;
rga_request.src.x_offset = 0;
rga_request.src.y_offset = 0;
rga_request.src.vir_w = src_buffer->src.w;
rga_request.src.vir_h = src_buffer->src.h;
rga_request.src.yrgb_addr = src_buffer->fd;
rga_request.src.uv_addr = 0;
rga_request.src.v_addr = 0;
rga_request.src.format = RGA_FORMAT_YCrCb_420_SP;
rga_request.dst.act_w = dst_buffer->width;
rga_request.dst.act_h = dst_buffer->height;
rga_request.dst.x_offset = 0;
rga_request.dst.y_offset = 0;
rga_request.dst.vir_w = dst_buffer->width;
rga_request.dst.vir_h = dst_buffer->height;
rga_request.dst.yrgb_addr = dst_buffer->fd;
rga_request.dst.uv_addr = 0;
rga_request.dst.v_addr = 0;
rga_request.dst.format = RGA_FORMAT_YCrCb_420_SP;
rga_request.scale_mode = 1;
rga_request.mmu_info.mmu_en = 1;
rga_request.mmu_info.mmu_flag = ((2 & 0x3) << 4) |
1 | (1 << 31 | 1 << 8 | 1 << 10);
rga_request.src.rd_mode = RGA_RASTER_MODE;
rga_request.dst.rd_mode = RGA_RASTER_MODE;
ret = rga_kernel_commit(&rga_request);
if (ret)
VEHICLE_DGERR("RGA_BLIT_SYNC failed(%d)\n", ret);
dst_buffer->src.f = dst_buffer->format;
dst_buffer->src.w = dst_buffer->width;
dst_buffer->src.h = dst_buffer->height;
dst_buffer->src.x = 0;
dst_buffer->src.y = 0;
/* save rga in buffer */
if (vehicle_dump_rga) {
struct file *filep = NULL;
loff_t pos = 0;
static bool file_ready;
static int frame_count;
VEHICLE_DG("@%s src->vir_addr[0](%d) addr[100](%d)\n",
__func__, ((char *)(src_buffer->vir_addr))[0],
((char *)(src_buffer->vir_addr))[100]);
if (!file_ready) {
int frame_len = src_buffer->src.w * src_buffer->src.h * 3 / 2;
char path[128] = {0};
VEHICLE_DG("save vop frame(%d) frame_len(%d)\n",
frame_count++, frame_len);
sprintf(path, "/data/rga_scaler_in_%zu_%zu.yuv",
src_buffer->src.w, src_buffer->src.h);
filep = filp_open(path, O_CREAT | O_RDWR, 0666);
if (IS_ERR(filep)) {
VEHICLE_DGERR(" %s filp_open failed!\n", path);
file_ready = false;
} else {
kernel_write(filep, src_buffer->vir_addr, frame_len, &pos);
filp_close(filep, NULL);
VEHICLE_INFO(" %s file saved ok!\n", path);
file_ready = true;
}
}
}
/* save rga out buffer */
if (vehicle_dump_rga) {
struct file *filep = NULL;
loff_t pos = 0;
static bool file_ready;
static int frame_count;
VEHICLE_DG("@%s dst->vir_addr[0](%d) addr[100](%d)\n",
__func__, ((char *)(dst_buffer->vir_addr))[0],
((char *)(dst_buffer->vir_addr))[100]);
if (!file_ready) {
/* NV12 */
int frame_len = dst_buffer->src.w * dst_buffer->src.h * 3 / 2;
char path[128] = {0};
VEHICLE_DG("save vop frame(%d) frame_len(%d)\n",
frame_count++, frame_len);
sprintf(path, "/data/rga_scaler_out_%zu_%zu.yuv",
dst_buffer->src.w, dst_buffer->src.h);
filep = filp_open(path, O_CREAT | O_RDWR, 0666);
if (IS_ERR(filep)) {
VEHICLE_DGERR(" %s filp_open failed!\n", path);
file_ready = false;
} else {
kernel_write(filep, dst_buffer->vir_addr, frame_len, &pos);
filp_close(filep, NULL);
VEHICLE_INFO(" %s file saved ok!\n", path);
file_ready = true;
}
}
}
src_buffer->state = FREE;
return 0;
}
static int rk_flinger_rga_blit(struct flinger *flinger,
struct graphic_buffer *src_buffer,
struct graphic_buffer *dst_buffer)
{
struct rga_req rga_request;
int sx, sy, sw, sh, ss, sf;
int dx, dy, dw, dh, ds, df;
int orientation;
int ret;
int src_fd, dst_fd;
if (!src_buffer || !dst_buffer)
return -EINVAL;
src_fd = src_buffer->fd;
dst_fd = dst_buffer->fd;
memset(&rga_request, 0, sizeof(rga_request));
orientation = src_buffer->rotation;
dst_buffer->rotation = src_buffer->rotation;
sx = src_buffer->src.x;
sy = src_buffer->src.y;
sw = src_buffer->src.w;
ss = src_buffer->src.s;
sh = src_buffer->src.h;
sf = rk_flinger_format_hal_to_rga(src_buffer->src.f);
VEHICLE_DG("%s src: sx:%d, sy:%d, sw:%d, ss:%d, sh:%d\n",
__func__, sx, sy, sw, ss, sh);
dx = src_buffer->dst.x;
dy = src_buffer->dst.y;
dw = src_buffer->dst.w;
ds = src_buffer->dst.s;
dh = src_buffer->dst.h;
df = rk_flinger_format_hal_to_rga(src_buffer->dst.f);
VEHICLE_DG("%s dst: dx:%d, dy:%d, dw:%d, ds:%d, dh:%d\n",
__func__, dx, dy, dw, ds, dh);
if (src_buffer->offset) {
sh += src_buffer->offset / src_buffer->len * sh;
sx = src_buffer->offset / src_buffer->len * sh;
src_fd = 0;
}
VEHICLE_DG("%s src: sx:%d, sy:%d, sw:%d, ss:%d, sh:%d\n",
__func__, sx, sy, sw, ss, sh);
switch (orientation) {
case RGA_TRANSFORM_ROT_0:
rga_request.rotate_mode = 0;
rga_request.sina = 0;
rga_request.cosa = 0;
rga_request.dst.vir_w = ds;
rga_request.dst.vir_h = dh;
rga_request.dst.act_w = dw;
rga_request.dst.act_h = dh;
rga_request.dst.x_offset = 0;
rga_request.dst.y_offset = 0;
break;
case RGA_TRANSFORM_FLIP_H:/*x mirror*/
rga_request.rotate_mode = 2;
rga_request.dst.vir_w = ds;
rga_request.dst.vir_h = dh;
rga_request.dst.act_w = dw;
rga_request.dst.act_h = dh;
rga_request.dst.x_offset = 0;
rga_request.dst.y_offset = 0;
break;
case RGA_TRANSFORM_FLIP_V:/*y mirror*/
rga_request.rotate_mode = 3;
rga_request.dst.vir_w = ds;
rga_request.dst.vir_h = dh;
rga_request.dst.act_w = dw;
rga_request.dst.act_h = dh;
rga_request.dst.x_offset = 0;
rga_request.dst.y_offset = 0;
break;
case RGA_TRANSFORM_ROT_90:
rga_request.rotate_mode = 1;
rga_request.sina = 65536;
rga_request.cosa = 0;
rga_request.dst.vir_w = ds;
rga_request.dst.vir_h = dh;
rga_request.dst.act_w = dh;
rga_request.dst.act_h = dw;
rga_request.dst.x_offset = 0;
rga_request.dst.y_offset = 0;
break;
case RGA_TRANSFORM_ROT_180:
rga_request.rotate_mode = 1;
rga_request.sina = 0;
rga_request.cosa = -65536;
rga_request.dst.vir_w = ds;
rga_request.dst.vir_h = dh;
rga_request.dst.act_w = dw;
rga_request.dst.act_h = dh;
rga_request.dst.x_offset = 0;
rga_request.dst.y_offset = 0;
break;
case RGA_TRANSFORM_ROT_270:
rga_request.rotate_mode = 1;
rga_request.sina = -65536;
rga_request.cosa = 0;
rga_request.dst.vir_w = ds;
rga_request.dst.vir_h = dh;
rga_request.dst.act_w = dh;
rga_request.dst.act_h = dw;
rga_request.dst.x_offset = 0;
rga_request.dst.y_offset = 0;
break;
default:
rga_request.rotate_mode = 0;
rga_request.sina = 0;
rga_request.cosa = 0;
rga_request.dst.vir_w = ds;
rga_request.dst.vir_h = dh;
rga_request.dst.act_w = dw;
rga_request.dst.act_h = dh;
rga_request.dst.x_offset = 0;
rga_request.dst.y_offset = 0;
break;
}
rga_request.src.yrgb_addr = src_fd;
rga_request.src.uv_addr = 0;
rga_request.src.v_addr = 0;
rga_request.dst.yrgb_addr = dst_fd;
rga_request.dst.uv_addr = 0;
rga_request.dst.v_addr = 0;
rga_request.src.vir_w = ss;
rga_request.src.vir_h = sh;
rga_request.src.format = sf;
rga_request.src.act_w = sw;
rga_request.src.act_h = sh;
rga_request.src.x_offset = 0;
rga_request.src.y_offset = 0;
rga_request.dst.format = df;
rga_request.clip.xmin = 0;
rga_request.clip.xmax = dw - 1;
rga_request.clip.ymin = 0;
rga_request.clip.ymax = dh - 1;
rga_request.scale_mode = 0;
rga_request.yuv2rgb_mode = 0x0 << 0; // yuvtoyuv config 0
/* yuv to rgb color space transform if need */
//rga_request.yuv2rgb_mode = 0x1 << 0; // limit range
//rga_request.yuv2rgb_mode = 0x2 << 0; // full range
rga_request.mmu_info.mmu_en = 1;
rga_request.mmu_info.mmu_flag = ((2 & 0x3) << 4) |
1 | (1 << 31 | 1 << 8 | 1 << 10);
rga_request.src.rd_mode = RGA_RASTER_MODE;
rga_request.dst.rd_mode = RGA_RASTER_MODE;
VEHICLE_DG("%s src_buffer->src.f(%zu) src_buffer->dst.f(%zu)",
__func__, src_buffer->src.f, src_buffer->dst.f);
ret = rga_kernel_commit(&rga_request);
if (ret)
VEHICLE_DGERR("RGA_BLIT_SYNC failed(%d)\n", ret);
return 0;
}
static int rk_flinger_rga_render(struct flinger *flinger,
struct graphic_buffer *src_buffer,
struct graphic_buffer *dst_buffer,
struct graphic_buffer *tmp_buffer)
{
int rotation;
if (!flinger || !src_buffer || !dst_buffer)
return -EINVAL;
if (dst_buffer && dst_buffer->rel_fence)
dst_buffer->rel_fence = NULL;
if ((src_buffer->rotation & RGA_TRANSFORM_ROT_MASK) &&
(src_buffer->rotation & RGA_TRANSFORM_FLIP_MASK)) {
rotation = flinger->v_cfg.rotate_mirror;
/* 1. rotate */
src_buffer->rotation = rotation & RGA_TRANSFORM_ROT_MASK;
rk_flinger_rga_blit(flinger, src_buffer, tmp_buffer);
rk_flinger_fill_buffer_rects(tmp_buffer, &src_buffer->dst,
&src_buffer->dst);
tmp_buffer->src.f = src_buffer->dst.f;
tmp_buffer->rotation = rotation & RGA_TRANSFORM_FLIP_MASK;
/* 2. mirror */
rk_flinger_rga_blit(flinger, tmp_buffer, dst_buffer);
rk_flinger_fill_buffer_rects(dst_buffer, &tmp_buffer->dst,
&tmp_buffer->dst);
dst_buffer->src.f = src_buffer->dst.f;
src_buffer->rotation = rotation;
} else {
rk_flinger_rga_blit(flinger, src_buffer, dst_buffer);
rk_flinger_fill_buffer_rects(dst_buffer, &src_buffer->dst,
&src_buffer->dst);
dst_buffer->src.f = src_buffer->dst.f;
}
/* save rga out buffer */
if (vehicle_dump_rga) {
struct file *filep = NULL;
loff_t pos = 0;
static bool file_ready;
static int frame_count;
VEHICLE_DG("@%s dst->vir_addr[0](%d) addr[100](%d)\n",
__func__, ((char *)(dst_buffer->vir_addr))[0],
((char *)(dst_buffer->vir_addr))[100]);
if (!file_ready) {
int frame_len = dst_buffer->src.w * dst_buffer->src.h * 3 / 2;//NV12
char path[128] = {0};
VEHICLE_DG("save vop frame(%d) frame_len(%d)\n",
frame_count++, frame_len);
sprintf(path, "/data/rga_render_%zu_%zu.yuv",
dst_buffer->src.w, dst_buffer->src.h);
filep = filp_open(path, O_CREAT | O_RDWR, 0666);
if (IS_ERR(filep)) {
VEHICLE_DGERR(" %s filp_open failed!\n", path);
file_ready = false;
} else {
kernel_write(filep, dst_buffer->vir_addr, frame_len, &pos);
filp_close(filep, NULL);
VEHICLE_INFO(" %s file saved ok!\n", path);
file_ready = true;
}
}
}
return 0;
}
static void rk_drm_vehicle_commit(struct flinger *flinger, struct graphic_buffer *buffer)
{
struct rockchip_drm_direct_show_commit_info commit_info;
int hdisplay = flinger->crtc->state->adjusted_mode.hdisplay;
int vdisplay = flinger->crtc->state->adjusted_mode.vdisplay;
commit_info.crtc = flinger->crtc;
commit_info.plane = flinger->plane;
commit_info.src_x = 0;
commit_info.src_y = 0;
commit_info.src_w = buffer->src.w;
commit_info.src_h = buffer->src.h;
// commit_info.src_w = buffer->drm_buffer->width;
// commit_info.src_h = buffer->drm_buffer->height;
/*center display*/
// commit_info.dst_x = (hdisplay - BUFFER_WIDTH) / 2;
// commit_info.dst_y = (vdisplay - BUFFER_HEIGHT) / 2;
// commit_info.dst_w = commit_info.src_w;
// commit_info.dst_h = commit_info.src_h;
/*full screen display */
commit_info.dst_x = 0;
commit_info.dst_y = 0;
commit_info.dst_w = hdisplay;
commit_info.dst_h = vdisplay;
commit_info.top_zpos = true;
commit_info.buffer = buffer->drm_buffer;
if (vehicle_dump_vop) {
struct file *filep = NULL;
loff_t pos = 0;
static bool file_ready;
static int frame_count;
if (!file_ready) {
int frame_len = buffer->drm_buffer->width *
buffer->drm_buffer->height * 3 / 2;//NV12
char path[128] = {0};
VEHICLE_DG("save vop frame(%d) frame_len(%d)\n",
frame_count++, frame_len);
sprintf(path, "/data/vop_commit_%d_%d.yuv",
buffer->drm_buffer->width,
buffer->drm_buffer->height);
filep = filp_open(path, O_CREAT | O_RDWR, 0666);
if (IS_ERR(filep)) {
VEHICLE_DGERR(" %s filp_open failed!\n", path);
file_ready = false;
} else {
kernel_write(filep,
buffer->drm_buffer->vir_addr[0], frame_len, &pos);
filp_close(filep, NULL);
VEHICLE_INFO(" %s file saved ok!\n", path);
file_ready = true;
}
}
}
rockchip_drm_direct_show_commit(flinger->drm_dev, &commit_info);
}
static int drop_frames_number;
static int rk_flinger_vop_show(struct flinger *flinger,
struct graphic_buffer *buffer)
{
if (!flinger || !buffer)
return -EINVAL;
VEHICLE_DG("flinger vop show buffer wxh(%zux%zu)\n",
buffer->src.w, buffer->src.h);
if (drop_frames_number > 0) {
VEHICLE_INFO("%s discard the frame num(%d)!\n", __func__, drop_frames_number);
drop_frames_number--;
return 0;
}
if (!flinger->running)
return 0;
/* get crtc and plane */
flinger->crtc = rockchip_drm_direct_show_get_crtc(flinger->drm_dev, flinger->crtc_name);
if (flinger->crtc == NULL) {
VEHICLE_DGERR("error: failed to get crtc\n");
return -EINVAL;
}
flinger->plane = rockchip_drm_direct_show_get_plane(flinger->drm_dev, flinger->plane_name);
if (flinger->plane == NULL) {
VEHICLE_DGERR("error: failed to get plane\n");
return -EINVAL;
}
rk_drm_vehicle_commit(flinger, buffer);
flinger->debug_vop_count++;
/* save vop show buffer */
if (vehicle_dump_vop) {
struct file *filep = NULL;
loff_t pos = 0;
static bool file_ready;
static int frame_count;
VEHICLE_DG("@%s buffer->vir_addr[0](%d) addr[100](%d)\n",
__func__, ((char *)(buffer->vir_addr))[0],
((char *)(buffer->vir_addr))[100]);
if (!file_ready) {
int frame_len = buffer->src.w * buffer->src.h * 3 / 2;//NV12
char path[128] = {0};
VEHICLE_DG("save vop frame(%d) frame_len(%d)\n",
frame_count++, frame_len);
sprintf(path, "/data/vop_show_%zu_%zu.yuv",
buffer->src.w, buffer->src.h);
filep = filp_open(path, O_CREAT | O_RDWR, 0666);
if (IS_ERR(filep)) {
VEHICLE_DGERR(" %s filp_open failed!\n", path);
file_ready = false;
} else {
kernel_write(filep, buffer->vir_addr, frame_len, &pos);
filp_close(filep, NULL);
VEHICLE_INFO(" %s file saved ok!\n", path);
file_ready = true;
}
}
}
return 0;
}
static void rk_flinger_first_done(struct work_struct *work)
{
struct graphic_buffer *buffer;
struct flinger *flg = flinger;
int i;
struct flinger *flg_test =
container_of(work, struct flinger, init_work);
struct vehicle_cfg *v_cfg = &flg_test->v_cfg;
if (!flg)
return;
for (i = 0; i < NUM_SOURCE_BUFFERS; i++) {
if (flg->source_buffer[i].state == FREE) {
buffer = &(flg->source_buffer[i]);
rk_flinger_set_rect(&buffer->src,
FORCE_XOFFSET, FORCE_YOFFSET,
v_cfg->width, v_cfg->height,
v_cfg->width, FORCE_FORMAT);
rk_flinger_set_buffer_rotation(buffer, v_cfg->rotate_mirror);
rk_flinger_cacultae_dst_rect_by_rotation(buffer);
buffer->dst.f = buffer->src.f;
VEHICLE_INFO("buffer[%d]->rotation(%d).\n",
i, buffer->rotation);
}
}
}
static void rk_flinger_render_show(struct work_struct *work)
{
struct graphic_buffer *src_buffer, *dst_buffer, *iep_buffer, *buffer;
/* struct queue_buffer *cur = NULL, *next = NULL; */
struct flinger *flg = flinger;
int i, found = 0;
static int count = -1;
static int last_src_index = -1;
bool cvbs_flag = true;
struct flinger *flg_test =
container_of(work, struct flinger, render_work);
struct vehicle_cfg *v_cfg = &flg_test->v_cfg;
src_buffer = NULL;
dst_buffer = NULL;
flg->source_index = 0;
do {
try_again:
wait_event_interruptible_timeout(flg->worker_wait,
atomic_read(&flg->worker_cond_atomic),
msecs_to_jiffies(1000000));
VEHICLE_DG("wake up enter, v_cfg.w*h(%dx%d)\n",
v_cfg->width, v_cfg->height);
if (atomic_read(&flg->worker_running_atomic) == 0) {
VEHICLE_INFO("%s loop exit\n", __func__);
break;
}
if (atomic_read(&flg->worker_cond_atomic) <= 0) {
/*printk("waiting 'worker_cond_atomic' timed out.");*/
goto try_again;
}
atomic_dec(&flg->worker_cond_atomic);
/* 1. find src buffer */
src_buffer = NULL;
found = last_src_index + 1;
for (i = 1; i < NUM_SOURCE_BUFFERS; i++, found++) {
found = found % NUM_SOURCE_BUFFERS;
if (flg->source_buffer[found].state == QUEUE) {
src_buffer = &flg->source_buffer[found];
last_src_index = found;
break;
}
}
if (!src_buffer || !src_buffer->fd) {
usleep_range(3000, 3100);
VEHICLE_DGERR("[%s:%d] error, no buffer\n", __func__, __LINE__);
goto try_again;
}
count++;
src_buffer->state = ACQUIRE;
/* save rkcif buffer */
if (vehicle_dump_cif) {
// struct file *filep = NULL;
struct file *filep;
loff_t pos = 0;
static bool file_ready;
static int frame_count;
VEHICLE_DG("src_buffer->vir_addr[0](%d) addr[100](%d)\n",
((char *)(src_buffer->vir_addr))[0],
((char *)(src_buffer->vir_addr))[100]);
if (!file_ready) {
//nv12 frame_len=w*h*3/2
int frame_len = src_buffer->src.w * src_buffer->src.h * 3 / 2;
char path[128] = {0};
VEHICLE_DG("save vop frame(%d) frame_len(%d)\n",
frame_count++, frame_len);
sprintf(path, "/data/cif_out_%zu_%zu.yuv",
src_buffer->src.w, src_buffer->src.h);
filep = filp_open(path, O_RDWR | O_CREAT, 0666);
if (IS_ERR(filep)) {
VEHICLE_DGERR(" %s filp_open failed!\n", path);
file_ready = false;
} else {
kernel_write(filep, src_buffer->vir_addr, frame_len, &pos);
filp_close(filep, NULL);
VEHICLE_INFO(" %s file saved ok!\n", path);
file_ready = true;
}
}
}
/* 2. find dst buffer */
dst_buffer = NULL;
iep_buffer = NULL;
/*get iep, rga, vop buffer*/
if (1) { //rotation by rga
if (flg->v_cfg.input_format == CIF_INPUT_FORMAT_PAL ||
flg->v_cfg.input_format == CIF_INPUT_FORMAT_NTSC) {
iep_buffer = &(flg->target_buffer
[NUM_TARGET_BUFFERS - 1]);
iep_buffer->state = ACQUIRE;
cvbs_flag = true;
} else {
cvbs_flag = false;
}
dst_buffer = &(flg->target_buffer
[count % (NUM_TARGET_BUFFERS - 1)]);
dst_buffer->state = ACQUIRE;
} else if (flg->v_cfg.input_format == CIF_INPUT_FORMAT_PAL ||
flg->v_cfg.input_format == CIF_INPUT_FORMAT_NTSC) {
iep_buffer = &(flg->target_buffer
[count % NUM_TARGET_BUFFERS]);
iep_buffer->state = ACQUIRE;
}
if (!iep_buffer || !iep_buffer->fd) {
if (iep_buffer)
iep_buffer->state = FREE;
}
/* 3 do deinterlace & rotation & display*/
if (!cvbs_flag) {
// YPbPr
VEHICLE_DG("it is ypbpr signal\n");
iep_buffer = &(flg->target_buffer[NUM_TARGET_BUFFERS - 1]);
iep_buffer->state = ACQUIRE;
//scaler by rga to force widthxheight display
rk_flinger_rga_render(flg, src_buffer, iep_buffer, dst_buffer);
src_buffer->state = FREE;
rk_flinger_rga_scaler(flg, iep_buffer, dst_buffer);
iep_buffer->state = FREE;
rk_flinger_vop_show(flg, dst_buffer);
for (i = 0; i < NUM_TARGET_BUFFERS; i++) {
buffer = &(flinger->target_buffer[i]);
if (buffer->state == DISPLAY)
buffer->state = FREE;
}
dst_buffer->state = DISPLAY;
} else {
// cvbs
VEHICLE_DG("it is a cvbs signal\n");
rk_flinger_rga_render(flg, src_buffer, dst_buffer, iep_buffer);
src_buffer->state = FREE;
rk_flinger_iep_deinterlace(flg, dst_buffer, iep_buffer);
dst_buffer->state = FREE;
rk_flinger_rga_scaler(flg, iep_buffer, dst_buffer);
rk_flinger_vop_show(flg, dst_buffer);
iep_buffer->state = FREE;
for (i = 0; i < NUM_TARGET_BUFFERS; i++) {
buffer = &(flinger->target_buffer[i]);
if (buffer->state == DISPLAY)
buffer->state = FREE;
}
dst_buffer->state = DISPLAY;
}
} while (1);
}
static int rk_flinger_queue_work(struct flinger *flinger,
struct graphic_buffer *src_buffer)
{
if (!flinger)
return -ENODEV;
if (!src_buffer) {
if (flinger->render_workqueue) {
INIT_WORK(&flinger->init_work, rk_flinger_first_done);
queue_work(flinger->render_workqueue,
&flinger->init_work);
}
}
if (flinger->render_workqueue) {
INIT_WORK(&flinger->render_work, rk_flinger_render_show);
queue_work(flinger->render_workqueue, &flinger->render_work);
}
return 0;
}
static struct graphic_buffer *
rk_flinger_lookup_buffer_by_phy_addr(unsigned long phy_addr)
{
struct graphic_buffer *buffer = NULL;
struct flinger *flg = flinger;
int i;
VEHICLE_DG("%s:phy_addr=%lx\n", __func__, phy_addr);
for (i = 1; i < NUM_SOURCE_BUFFERS; i++) {
if (flg->source_buffer[i].state == DEQUEUE) {
buffer = &(flg->source_buffer[i]);
if (buffer && (buffer->offset +
buffer->phy_addr == phy_addr)) {
buffer->state = QUEUE;
break;
}
}
}
if (i < NUM_SOURCE_BUFFERS)
return buffer;
else
return NULL;
}
static bool vehicle_rotation_param_check(struct vehicle_cfg *v_cfg)
{
switch (v_cfg->rotate_mirror & RGA_TRANSFORM_ROT_MASK) {
case RGA_TRANSFORM_ROT_90:
case RGA_TRANSFORM_ROT_270:
case RGA_TRANSFORM_ROT_0:
case RGA_TRANSFORM_ROT_180:
return true;
default:
VEHICLE_INFO("invalid rotate-mirror param %d\n",
v_cfg->rotate_mirror);
v_cfg->rotate_mirror = v_cfg->rotate_mirror & RGA_TRANSFORM_FLIP_MASK;
return false;
}
switch (v_cfg->rotate_mirror & RGA_TRANSFORM_FLIP_MASK) {
case RGA_TRANSFORM_FLIP_H:
case RGA_TRANSFORM_FLIP_V:
return true;
default:
VEHICLE_INFO("invalid rotate-mirror param %d\n",
v_cfg->rotate_mirror);
v_cfg->rotate_mirror = v_cfg->rotate_mirror & RGA_TRANSFORM_ROT_MASK;
return false;
}
}
int vehicle_flinger_reverse_open(struct vehicle_cfg *v_cfg,
bool android_is_ready)
{
int i;
int width;
int height;
struct flinger *flg = flinger;
struct graphic_buffer *buffer;
int hal_format;
width = v_cfg->width;
height = v_cfg->height;
if (!flinger)
return -ENODEV;
vehicle_rotation_param_check(v_cfg);
if (v_cfg->output_format == CIF_OUTPUT_FORMAT_422)
hal_format = HAL_PIXEL_FORMAT_YCbCr_422_SP;
else
hal_format = HAL_PIXEL_FORMAT_YCrCb_NV12;
/* 1. reinit buffer format */
for (i = 0; i < NUM_SOURCE_BUFFERS; i++) {
buffer = &(flg->source_buffer[i]);
rk_flinger_set_rect(&buffer->src,
0, 0, width,
height, width, hal_format);
rk_flinger_set_buffer_rotation(buffer, v_cfg->rotate_mirror);
rk_flinger_cacultae_dst_rect_by_rotation(buffer);
buffer->dst.f = buffer->src.f;
buffer->state = FREE;
}
for (i = 0; i < NUM_TARGET_BUFFERS; i++) {
buffer = &(flg->target_buffer[i]);
buffer->state = FREE;
}
/*2. fill buffer info*/
for (i = 0; i < NUM_SOURCE_BUFFERS && i < MAX_BUF_NUM; i++) {
v_cfg->buf_phy_addr[i] = flinger->source_buffer[i].phy_addr;
VEHICLE_DG("buf_phy_addr=%x, i=%d", v_cfg->buf_phy_addr[i], i);
}
v_cfg->buf_num = NUM_SOURCE_BUFFERS;
flg->cvbs_field_count = 0;
memcpy(&flg->v_cfg, v_cfg, sizeof(struct vehicle_cfg));
flg->running = true;
drop_frames_number = v_cfg->drop_frames;
return 0;
}
int vehicle_flinger_reverse_close(bool android_is_ready)
{
struct flinger *flg = flinger;
flg->running = false;
if (flg->drm_dev && flg->plane)
rockchip_drm_direct_show_disable_plane(flg->drm_dev, flg->plane);
VEHICLE_DG("%s(%d) done\n", __func__, __LINE__);
return 0;
}
unsigned long vehicle_flinger_request_cif_buffer(void)
{
struct graphic_buffer *src_buffer = NULL;
struct flinger *flg = flinger;
static int last_src_index = -1;
int found;
int i;
src_buffer = NULL;
for (i = 1; i < NUM_SOURCE_BUFFERS; i++) {
found = (last_src_index + i) % NUM_SOURCE_BUFFERS;
VEHICLE_DG("%s,flg->source_buffer[%d].state(%d)",
__func__, found, flg->source_buffer[found].state);
if (flg->source_buffer[found].state == FREE) {
src_buffer = &flg->source_buffer[found];
last_src_index = found;
src_buffer->state = DEQUEUE;
break;
}
}
if (i < NUM_SOURCE_BUFFERS)
return src_buffer->phy_addr;
else
return 0;
}
void vehicle_flinger_commit_cif_buffer(u32 buf_phy_addr)
{
struct graphic_buffer *buffer = NULL;
struct flinger *flg = flinger;
if (!flg)
return;
buffer = rk_flinger_lookup_buffer_by_phy_addr(buf_phy_addr);
if (buffer) {
buffer->timestamp = ktime_get();
atomic_inc(&flg->worker_cond_atomic);
flg->debug_cif_count++;
wake_up(&flg->worker_wait);
} else {
VEHICLE_DGERR("%x, no free buffer\n", buf_phy_addr);
}
}