blob: 7722a74a29f5d104f1d90240429c306b4c3080a6 [file] [log] [blame]
/*
* drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/compat.h>
#include <linux/kernel.h>
#include <linux/amlogic/media/ppmgr/ppmgr.h>
#include <linux/amlogic/media/ppmgr/ppmgr_status.h>
#include <linux/platform_device.h>
/*#include <linux/amlogic/ge2d/ge2d_main.h>*/
#include <linux/amlogic/media/ge2d/ge2d.h>
#include <linux/amlogic/media/utils/amlog.h>
#include <linux/ctype.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/vfm/vframe_provider.h>
#include <linux/amlogic/media/vfm/vframe_receiver.h>
#include <linux/of_fdt.h>
#include <linux/of_reserved_mem.h>
#include <linux/amlogic/media/utils/amports_config.h>
#include <linux/amlogic/media/video_sink/video.h>
#include "ppmgr_log.h"
#include "ppmgr_pri.h"
#include "ppmgr_dev.h"
#define PPMGRDRV_INFO(fmt, args...) pr_info("PPMGRDRV: info: "fmt"", ## args)
#define PPMGRDRV_DBG(fmt, args...) pr_debug("PPMGRDRV: dbg: "fmt"", ## args)
#define PPMGRDRV_WARN(fmt, args...) pr_warn("PPMGRDRV: warn: "fmt"", ## args)
#define PPMGRDRV_ERR(fmt, args...) pr_err("PPMGRDRV: err: "fmt"", ## args)
/***********************************************************************
*
* global status.
*
************************************************************************/
static int ppmgr_enable_flag;
static int ppmgr_flag_change;
static int property_change;
static int buff_change;
static int inited_ppmgr_num;
static enum platform_type_t platform_type = PLATFORM_MID;
/*static struct platform_device *ppmgr_core_device = NULL;*/
struct ppmgr_device_t ppmgr_device;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
/* extern void Reset3Dclear(void); */
/* extern void Set3DProcessPara(unsigned mode); */
#endif
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
static bool scaler_pos_reset;
#endif
static struct ppmgr_dev_reg_s ppmgr_dev_reg;
enum platform_type_t get_platform_type(void)
{
return platform_type;
}
int get_bypass_mode(void)
{
return ppmgr_device.bypass;
}
int get_property_change(void)
{
return property_change;
}
void set_property_change(int flag)
{
property_change = flag;
}
int get_buff_change(void)
{
return buff_change;
}
void set_buff_change(int flag)
{
buff_change = flag;
}
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
bool get_scaler_pos_reset(void)
{
return scaler_pos_reset;
}
void set_scaler_pos_reset(bool flag)
{
scaler_pos_reset = flag;
}
#endif
int get_ppmgr_status(void)
{
return ppmgr_enable_flag;
}
void set_ppmgr_status(int flag)
{
if (flag != ppmgr_enable_flag)
ppmgr_flag_change = 1;
if (flag >= 0)
ppmgr_enable_flag = flag;
else
ppmgr_enable_flag = 0;
}
/***********************************************************************
*
* 3D function.
*
************************************************************************/
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
unsigned int get_ppmgr_3dmode(void)
{
return ppmgr_device.ppmgr_3d_mode;
}
void set_ppmgr_3dmode(unsigned int mode)
{
if (ppmgr_device.ppmgr_3d_mode != mode) {
ppmgr_device.ppmgr_3d_mode = mode;
Set3DProcessPara(ppmgr_device.ppmgr_3d_mode);
Reset3Dclear();
/*property_change = 1;*/
}
}
unsigned int get_ppmgr_viewmode(void)
{
return ppmgr_device.viewmode;
}
void set_ppmgr_viewmode(unsigned int mode)
{
if ((ppmgr_device.viewmode != mode) && (mode < VIEWMODE_MAX)) {
ppmgr_device.viewmode = mode;
Reset3Dclear();
/*property_change = 1;*/
}
}
unsigned int get_ppmgr_scaledown(void)
{
return ppmgr_device.scale_down;
}
void set_ppmgr_scaledown(unsigned int scale_down)
{
if ((ppmgr_device.scale_down != scale_down) && (scale_down < 3)) {
ppmgr_device.scale_down = scale_down;
Reset3Dclear();
}
}
unsigned int get_ppmgr_direction3d(void)
{
return ppmgr_device.direction_3d;
}
void set_ppmgr_direction3d(unsigned int angle)
{
if ((ppmgr_device.direction_3d != angle) && (angle < 4)) {
ppmgr_device.direction_3d = angle;
Reset3Dclear();
/*property_change = 1;*/
}
}
#endif
/***********************************************************************
*
* Utilities.
*
************************************************************************/
static ssize_t _ppmgr_angle_write(unsigned long val)
{
unsigned long angle = val;
if (angle > 3) {
if (angle == 90)
angle = 1;
else if (angle == 180)
angle = 2;
else if (angle == 270)
angle = 3;
else {
PPMGRDRV_ERR("invalid orientation value\n");
PPMGRDRV_ERR("you should set 0 or 0 for 0 clockwise\n");
PPMGRDRV_ERR("1 or 90 for 90 clockwise\n");
PPMGRDRV_ERR("2 or 180 for 180 clockwise\n");
PPMGRDRV_ERR("3 or 270 for 270 clockwise\n");
return -EINVAL;
}
}
ppmgr_device.global_angle = angle;
ppmgr_device.videoangle = (angle + ppmgr_device.orientation) % 4;
if (!ppmgr_device.use_prot) {
if (angle != ppmgr_device.angle) {
property_change = 1;
PPMGRDRV_INFO("ppmgr angle:%x\n", ppmgr_device.angle);
PPMGRDRV_INFO("orient:%x\n", ppmgr_device.orientation);
PPMGRDRV_INFO("vidangl:%x\n", ppmgr_device.videoangle);
}
} else {
if (angle != ppmgr_device.angle) {
set_video_angle(angle);
PPMGRDRV_INFO("prot angle:%ld\n", angle);
}
}
ppmgr_device.angle = angle;
return 0;
}
/***********************************************************************
*
* class property info.
*
************************************************************************/
#define PPMGR_CLASS_NAME "ppmgr"
static int parse_para(const char *para, int para_num, int *result)
{
char *token = NULL;
char *params, *params_base;
int *out = result;
int len = 0, count = 0;
int res = 0;
int ret = 0;
if (!para)
return 0;
params = kstrdup(para, GFP_KERNEL);
params_base = params;
token = params;
len = strlen(token);
do {
token = strsep(&params, " ");
while (token && (isspace(*token)
|| !isgraph(*token)) && len) {
token++;
len--;
}
if ((len == 0) || (!token))
break;
ret = kstrtoint(token, 0, &res);
if (ret < 0) {
PPMGRDRV_ERR("ERR convert %s to long int!\n", token);
break;
}
len = strlen(token);
*out++ = res;
count++;
} while ((token) && (count < para_num) && (len > 0));
kfree(params_base);
return count;
}
static ssize_t angle_read(struct class *cla, struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 80, "current angel is %d\n",
ppmgr_device.global_angle);
}
static ssize_t angle_write(struct class *cla, struct class_attribute *attr,
const char *buf, size_t count)
{
/*
ssize_t size;
char *endp;
unsigned long angle = simple_strtoul(buf, &endp, 0);
*/
long angle;
int ret = kstrtoul(buf, 0, &angle);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
if (angle > 3 || angle < 0) {
/* size = endp - buf; */
return count;
}
if (_ppmgr_angle_write(angle) < 0)
return -EINVAL;
/* size = endp - buf; */
return count;
}
int get_use_prot(void)
{
return ppmgr_device.use_prot;
}
EXPORT_SYMBOL(get_use_prot);
static ssize_t disable_prot_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(buf, 40, "%d\n", ppmgr_device.disable_prot);
}
static ssize_t disable_prot_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
size_t r;
u32 s_value;
r = kstrtoint(buf, 0, &s_value);
if (r != 0)
return -EINVAL;
ppmgr_device.disable_prot = s_value;
return strnlen(buf, count);
}
static ssize_t orientation_read(struct class *cla, struct class_attribute *attr,
char *buf)
{
/*ppmgr_device_t* ppmgr_dev=(ppmgr_device_t*)cla;*/
return snprintf(buf, 80, "current orientation is %d\n",
ppmgr_device.orientation * 90);
}
/* set the initial orientation for video,
* it should be set before video start.
*/
static ssize_t orientation_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
ssize_t ret = -EINVAL; /* , size; */
/* char *endp; */
unsigned long tmp;
/* unsigned angle = simple_strtoul(buf, &endp, 0); */
unsigned int angle;
ret = kstrtoul(buf, 0, &tmp);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
angle = tmp;
/*if (property_change) return ret;*/
if (angle > 3) {
if (angle == 90)
angle = 1;
else if (angle == 180)
angle = 2;
else if (angle == 270)
angle = 3;
else {
PPMGRDRV_ERR("invalid orientation value\n");
PPMGRDRV_ERR("you should set 0 or 0 for 0 clockwise\n");
PPMGRDRV_ERR("1 or 90 for 90 clockwise\n");
PPMGRDRV_ERR("2 or 180 for 180 clockwise\n");
PPMGRDRV_ERR("3 or 270 for 270 clockwise\n");
return ret;
}
}
ppmgr_device.orientation = angle;
ppmgr_device.videoangle =
(ppmgr_device.angle + ppmgr_device.orientation) % 4;
PPMGRDRV_INFO("angle:%d,orientation:%d,videoangle:%d\n",
ppmgr_device.angle, ppmgr_device.orientation,
ppmgr_device.videoangle);
/* size = endp - buf; */
return count;
}
static ssize_t bypass_read(struct class *cla, struct class_attribute *attr,
char *buf)
{
/*ppmgr_device_t* ppmgr_dev=(ppmgr_device_t*)cla;*/
return snprintf(buf, 80, "current bypass is %d\n", ppmgr_device.bypass);
}
static ssize_t bypass_write(struct class *cla, struct class_attribute *attr,
const char *buf, size_t count)
{
/*
ssize_t size;
char *endp;
*/
long tmp;
/* ppmgr_device.bypass = simple_strtoul(buf, &endp, 0); */
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
ppmgr_device.bypass = tmp;
/* size = endp - buf; */
return count;
}
static ssize_t rect_read(struct class *cla, struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 80, "rotate rect:\nl:%d,t:%d,w:%d,h:%d\n",
ppmgr_device.left, ppmgr_device.top, ppmgr_device.width,
ppmgr_device.height);
}
static ssize_t rect_write(struct class *cla, struct class_attribute *attr,
const char *buf, size_t count)
{
char *errstr =
"data error,access string is \"left,top,width,height\"\n";
char *strp = (char *)buf;
char *endp = NULL;
int value_array[4];
static int buflen;
static char *tokenlen;
int i;
long tmp;
int ret;
buflen = strlen(buf);
value_array[0] = value_array[1] = value_array[2] = value_array[3] = -1;
for (i = 0; i < 4; i++) {
if (buflen == 0) {
PPMGRDRV_ERR("%s\n", errstr);
return -EINVAL;
}
tokenlen = strnchr(strp, buflen, ',');
if (tokenlen != NULL)
*tokenlen = '\0';
/* value_array[i] = simple_strtoul(strp, &endp, 0); */
ret = kstrtol(strp, 0, &tmp);
if (ret != 0) {
PPMGRDRV_ERR("ERROR convert %s to long int!\n", strp);
return ret;
}
value_array[i] = tmp;
if ((endp - strp) > (tokenlen - strp))
break;
if (tokenlen != NULL) {
*tokenlen = ',';
strp = tokenlen + 1;
buflen = strlen(strp);
} else
break;
}
if (value_array[0] >= 0)
ppmgr_device.left = value_array[0];
if (value_array[1] >= 0)
ppmgr_device.left = value_array[1];
if (value_array[2] > 0)
ppmgr_device.left = value_array[2];
if (value_array[3] > 0)
ppmgr_device.left = value_array[3];
return count;
}
static ssize_t disp_read(struct class *cla, struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 80, "disp width is %d ; disp height is %d\n",
ppmgr_device.disp_width, ppmgr_device.disp_height);
}
static void set_disp_para(const char *para)
{
int parsed[2];
if (likely(parse_para(para, 2, parsed) == 2)) {
int w, h;
w = parsed[0];
h = parsed[1];
if ((ppmgr_device.disp_width != w) || (ppmgr_device.disp_height
!= h))
buff_change = 1;
ppmgr_device.disp_width = w;
ppmgr_device.disp_height = h;
}
}
static ssize_t disp_write(struct class *cla, struct class_attribute *attr,
const char *buf, size_t count)
{
set_disp_para(buf);
return count;
}
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
/* extern int video_scaler_notify(int flag); */
/* extern void amvideo_set_scaler_para(int x, int y, int w, int h, int flag); */
static ssize_t ppscaler_read(struct class *cla, struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 80, "current ppscaler mode is %s\n",
(ppmgr_device.ppscaler_flag) ? "enabled" : "disabled");
}
static ssize_t ppscaler_write(struct class *cla, struct class_attribute *attr,
const char *buf, size_t count)
{
/*
ssize_t size;
char *endp;
*/
long tmp;
/* int flag simple_strtoul(buf, &endp, 0); */
int flag;
int ret = kstrtol(buf, 0, &tmp);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
flag = tmp;
if ((flag < 2) && (flag != ppmgr_device.ppscaler_flag)) {
if (flag)
video_scaler_notify(1);
else
video_scaler_notify(0);
ppmgr_device.ppscaler_flag = flag;
if (ppmgr_device.ppscaler_flag == 0)
set_scaler_pos_reset(true);
}
/* size = endp - buf; */
return count;
}
static void set_ppscaler_para(const char *para)
{
int parsed[5];
if (likely(parse_para(para, 5, parsed) == 5)) {
ppmgr_device.scale_h_start = parsed[0];
ppmgr_device.scale_v_start = parsed[1];
ppmgr_device.scale_h_end = parsed[2];
ppmgr_device.scale_v_end = parsed[3];
amvideo_set_scaler_para(
ppmgr_device.scale_h_start,
ppmgr_device.scale_v_start,
ppmgr_device.scale_h_end
- ppmgr_device.scale_h_start + 1,
ppmgr_device.scale_v_end
-ppmgr_device.scale_v_start + 1,
parsed[4]);
}
}
static ssize_t ppscaler_rect_read(struct class *cla,
struct class_attribute *attr, char *buf)
{
return snprintf(
buf, 80, "ppscaler rect:\nx:%d,y:%d,w:%d,h:%d\n",
ppmgr_device.scale_h_start, ppmgr_device.scale_v_start,
ppmgr_device.scale_h_end - ppmgr_device.scale_h_start + 1,
ppmgr_device.scale_v_end - ppmgr_device.scale_v_start + 1);
}
static ssize_t ppscaler_rect_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
set_ppscaler_para(buf);
return count;
}
#endif
static ssize_t receiver_read(struct class *cla, struct class_attribute *attr,
char *buf)
{
if (ppmgr_device.receiver == 1)
return snprintf(buf, 80, "video stream out to video4linux\n");
else
return snprintf(buf, 80, "video stream out to vlayer\n");
}
static ssize_t receiver_write(struct class *cla, struct class_attribute *attr,
const char *buf, size_t count)
{
/*
ssize_t size;
char *endp;
*/
long tmp;
int ret;
if (buf[0] != '0' && buf[0] != '1') {
PPMGRDRV_ERR("device to whitch the video stream decoded\n");
PPMGRDRV_ERR("0: to video layer\n");
PPMGRDRV_ERR("1: to amlogic video4linux /dev/video10\n");
return 0;
}
/* ppmgr_device.receiver = simple_strtoul(buf, &endp, 0); */
ret = kstrtoul(buf, 0, &tmp);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
ppmgr_device.receiver = tmp;
vf_ppmgr_reset(0);
/* size = endp - buf; */
return count;
}
static ssize_t platform_type_read(struct class *cla,
struct class_attribute *attr, char *buf)
{
if (platform_type == PLATFORM_TV)
return snprintf(buf, 80, "current platform is TV\n");
else if (platform_type == PLATFORM_MID)
return snprintf(buf, 80, "current platform is MID\n");
else if (platform_type == PLATFORM_MID_VERTICAL)
return snprintf(buf, 80, "current platform is vertical MID\n");
else
return snprintf(buf, 80, "current platform is MBX\n");
}
static ssize_t platform_type_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
/*
ssize_t size;
char *endp;
*/
long tmp;
/* platform_type = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &tmp);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
platform_type = tmp;
/* size = endp - buf; */
return count;
}
static ssize_t tb_detect_read(struct class *cla,
struct class_attribute *attr, char *buf)
{
unsigned int detect = ppmgr_device.tb_detect;
return snprintf(buf, 80, "current T/B detect mode is %d\n",
detect);
}
static ssize_t tb_detect_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
/*
ssize_t size;
char *endp;
*/
unsigned long tmp;
int ret = kstrtoul(buf, 0, &tmp);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
ppmgr_device.tb_detect = tmp;
/* size = endp - buf; */
return count;
}
static ssize_t tb_detect_period_read(struct class *cla,
struct class_attribute *attr, char *buf)
{
unsigned int period = ppmgr_device.tb_detect_period;
return snprintf(buf, 80, "current T/B detect period is %d\n",
period);
}
static ssize_t tb_detect_period_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
/*
ssize_t size;
char *endp;
*/
unsigned long tmp;
/* platform_type = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &tmp);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
ppmgr_device.tb_detect_period = tmp;
/* size = endp - buf; */
return count;
}
static ssize_t tb_detect_len_read(struct class *cla,
struct class_attribute *attr, char *buf)
{
unsigned int len = ppmgr_device.tb_detect_buf_len;
return snprintf(buf, 80, "current T/B detect buff len is %d\n",
len);
}
static ssize_t tb_detect_len_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
/*
ssize_t size;
char *endp;
*/
unsigned long tmp;
/* platform_type = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &tmp);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
if ((tmp < 6) || (tmp > 16)) {
PPMGRDRV_INFO(
"tb detect buffer len should be 6~16 (%ld)\n", tmp);
tmp = 6;
}
ppmgr_device.tb_detect_buf_len = tmp;
/* size = endp - buf; */
return count;
}
static ssize_t tb_detect_mute_read(struct class *cla,
struct class_attribute *attr, char *buf)
{
unsigned int mute = ppmgr_device.tb_detect_init_mute;
return snprintf(buf, 80, "current T/B detect init mute is %d\n",
mute);
}
static ssize_t tb_detect_mute_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
/*
ssize_t size;
char *endp;
*/
unsigned long tmp;
/* platform_type = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &tmp);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
PPMGRDRV_INFO(
"tb detect init mute is %ld\n", tmp);
ppmgr_device.tb_detect_init_mute = tmp;
/* size = endp - buf; */
return count;
}
static ssize_t tb_status_read(struct class *cla,
struct class_attribute *attr, char *buf)
{
get_tb_detect_status();
return snprintf(buf, 80, "#################\n");
}
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
static ssize_t _3dmode_read(
struct class *cla, struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "current 3d mode is 0x%x\n",
ppmgr_device.ppmgr_3d_mode);
}
static ssize_t _3dmode_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
ssize_t size;
char *endp;
unsigned long mode;
/* unsigned mode = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &mode);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
set_ppmgr_3dmode(mode);
size = endp - buf;
return count;
}
static ssize_t viewmode_read(
struct class *cla, struct class_attribute *attr, char *buf)
{
const char *viewmode_str[] const = {
"normal", "full", "4:3", "16:9", "1:1"};
return snprintf(buf, 80, "current view mode is %d:%s\n",
ppmgr_device.viewmode,
viewmode_str[ppmgr_device.viewmode]);
}
static ssize_t viewmode_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
ssize_t size;
char *endp;
unsigned long mode;
/* unsigned mode = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &mode);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
set_ppmgr_viewmode(mode);
size = endp - buf;
return count;
}
static ssize_t doublemode_read(
struct class *cla, struct class_attribute *attr, char *buf)
{
const char *doublemode_str[] const = {
"normal", "horizontal double", "vertical double"};
unsigned int mode = get_ppmgr_3dmode();
mode = ((mode & PPMGR_3D_PROCESS_DOUBLE_TYPE) >>
PPMGR_3D_PROCESS_DOUBLE_TYPE_SHIFT);
return snprintf(buf, 80, "current 3d double scale mode is %d:%s\n",
mode, doublemode_str[mode]);
}
static ssize_t doublemode_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
ssize_t size;
char *endp;
unsigned long flag;
unsigned int mode;
/* unsigned flag = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &flag);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
mode = get_ppmgr_3dmode();
mode = (mode & (~PPMGR_3D_PROCESS_DOUBLE_TYPE)) |
((flag << PPMGR_3D_PROCESS_DOUBLE_TYPE_SHIFT) &
(PPMGR_3D_PROCESS_DOUBLE_TYPE));
set_ppmgr_3dmode(mode);
size = endp - buf;
return count;
}
static ssize_t switchmode_read(
struct class *cla, struct class_attribute *attr, char *buf)
{
const char *switchmode_str[] const = {"disable", "enable"};
unsigned int mode = get_ppmgr_3dmode();
unsigned int flag = (mode & PPMGR_3D_PROCESS_SWITCH_FLAG) ? 1 : 0;
return snprintf(buf, 80, "current 3d switch mode is %d:%s\n",
flag, switchmode_str[flag]);
}
static ssize_t switchmode_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
ssize_t size;
char *endp;
unsigned long flag;
unsigned int mode;
/* int flag = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &flag);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
mode = get_ppmgr_3dmode();
if (!flag)
mode = mode & (~PPMGR_3D_PROCESS_SWITCH_FLAG);
else
mode = mode | PPMGR_3D_PROCESS_SWITCH_FLAG;
set_ppmgr_3dmode(mode);
size = endp - buf;
return count;
}
static ssize_t direction_3d_read(
struct class *cla, struct class_attribute *attr, char *buf)
{
const char *direction_str[] const = {
"0 degree", "90 degree", "180 degree", "270 degree"};
/*unsigned mode = get_ppmgr_3dmode();*/
/* mode = ((mode & PPMGR_3D_PROCESS_3D_ROTATE_DIRECTION_MASK)
* >>PPMGR_3D_PROCESS_3D_ROTATE_DIRECTION_VALUE_SHIFT);
*/
/* return snprintf(buf,80,"current 3d direction is %d:%s\n",
* mode,direction_str[mode]);
*/
unsigned int angle = get_ppmgr_direction3d();
return snprintf(buf, 80, "current 3d direction is %d:%s\n",
angle, direction_str[angle]);
}
static ssize_t direction_3d_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
ssize_t size;
char *endp;
/* int flag = simple_strtoul(buf, &endp, 0); */
unsigned long flag;
int ret = kstrtoul(buf, 0, &flag);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
/*unsigned mode = get_ppmgr_3dmode();*/
/* mode = (mode & (~PPMGR_3D_PROCESS_3D_ROTATE_DIRECTION_MASK))
* |((flag<<PPMGR_3D_PROCESS_3D_ROTATE_DIRECTION_VALUE_SHIFT)&
* (PPMGR_3D_PROCESS_3D_ROTATE_DIRECTION_MASK));
*/
/*set_ppmgr_3dmode(mode);*/
set_ppmgr_direction3d(flag);
size = endp - buf;
return count;
}
static ssize_t scale_down_read(
struct class *cla, struct class_attribute *attr, char *buf)
{
const char *value_str[] const = {"noraml", "div 2", "div 3", "div 4"};
unsigned int mode = ppmgr_device.scale_down;
return snprintf(buf, 80, "current scale down value is %d:%s\n",
mode + 1, value_str[mode]);
}
static ssize_t scale_down_write(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
ssize_t size;
char *endp;
/* unsigned mode = simple_strtoul(buf, &endp, 0); */
unsigned long mode;
int ret = kstrtoul(buf, 0, &mode);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
set_ppmgr_scaledown(mode);
size = endp - buf;
return count;
}
/* *****************************************************************
* 3D TV usage
* *****************************************************************
*/
struct frame_info_t frame_info;
static int ppmgr_view_mode;
static int ppmgr_vertical_sample = 1;
static int ppmgr_scale_width = 800;
int ppmgr_cutwin_top;
int ppmgr_cutwin_left;
int get_ppmgr_change_notify(void)
{
if (ppmgr_flag_change) {
ppmgr_flag_change = 0;
return 1;
} else {
return 0;
}
}
int get_ppmgr_view_mode(void)
{
return ppmgr_view_mode;
}
int get_ppmgr_vertical_sample(void)
{
return ppmgr_vertical_sample;
}
int get_ppmgr_scale_width(void)
{
return ppmgr_scale_width;
}
static int depth = 3200; /*12.5 pixels*/
void set_depth(int para)
{
depth = para;
}
int get_depth(void)
{
return depth;
}
static ssize_t read_depth(
struct class *cla, struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "current depth is %d\n", depth);
}
static ssize_t write_depth(
struct class *cla, struct class_attribute *attr, const char *buf,
size_t count)
{
unsigned long r;
/* r = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &r);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
set_depth(r);
return count;
}
static ssize_t read_view_mode(
struct class *cla, struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "current view mode is %d\n", ppmgr_view_mode);
}
static ssize_t write_view_mode(
struct class *cla, struct class_attribute *attr, const char *buf,
size_t count)
{
unsigned long r;
/* r = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &r);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
ppmgr_view_mode = r;
return count;
}
static ssize_t read_vertical_sample(
struct class *cla, struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "ppmgr_vertical_sample %d\n",
ppmgr_vertical_sample);
}
static ssize_t write_vertical_sample(
struct class *cla, struct class_attribute *attr, const char *buf,
size_t count)
{
unsigned long r;
/* r = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &r);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
ppmgr_vertical_sample = r;
return count;
}
static ssize_t read_scale_width(
struct class *cla, struct class_attribute *attr, char *buf)
{
return snprintf(buf, 80, "ppmgr_scale_width is %d\n",
ppmgr_scale_width);
}
static ssize_t write_scale_width(struct class *cla,
struct class_attribute *attr, const char *buf, size_t count)
{
unsigned long r;
/* r = simple_strtoul(buf, &endp, 0); */
int ret = kstrtoul(buf, 0, &r);
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
ppmgr_scale_width = r;
return count;
}
static void set_cut_window(const char *para)
{
int parsed[2];
if (likely(parse_para(para, 2, parsed) == 2)) {
int top, left;
top = parsed[0];
left = parsed[1];
ppmgr_cutwin_top = top;
ppmgr_cutwin_left = left;
}
}
static ssize_t cut_win_show(
struct class *cla, struct class_attribute *attr, char *buf)
{
return snprintf(
buf, 80, "cut win top is %d ; cut win left is %d\n",
ppmgr_cutwin_top, ppmgr_cutwin_left);
}
static ssize_t cut_win_store(
struct class *cla, struct class_attribute *attr, const char *buf,
size_t count)
{
set_cut_window(buf);
return strnlen(buf, count);
}
#endif
static ssize_t mirror_read(struct class *cla, struct class_attribute *attr,
char *buf)
{
if (ppmgr_device.mirror_flag == 1)
return snprintf(
buf,
80,
"currnet mirror mode is l-r mirror mode. value is: %d.\n",
ppmgr_device.mirror_flag);
else if (ppmgr_device.mirror_flag == 2)
return snprintf(
buf,
80,
"currnet mirror mode is t-b mirror mode. value is: %d.\n",
ppmgr_device.mirror_flag);
else
return snprintf(
buf, 80,
"currnet mirror mode is normal mode. value is: %d.\n",
ppmgr_device.mirror_flag);
}
static ssize_t mirror_write(struct class *cla, struct class_attribute *attr,
const char *buf, size_t count)
{
/*
ssize_t size;
char *endp;
*/
long tmp;
int ret = kstrtol(buf, 0, &tmp);
/* ppmgr_device.mirror_flag = simple_strtoul(buf, &endp, 0); */
if (ret != 0) {
PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf);
return ret;
}
ppmgr_device.mirror_flag = tmp;
if (ppmgr_device.mirror_flag > 2)
ppmgr_device.mirror_flag = 0;
/* size = endp - buf; */
return count;
}
/* *************************************************************
* 3DTV usage
* *************************************************************
*/
/* extern int vf_ppmgr_get_states(struct vframe_states *states); */
static ssize_t ppmgr_vframe_states_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
int ret = 0;
struct vframe_states states;
if (vf_ppmgr_get_states(&states) == 0) {
ret += sprintf(buf + ret, "vframe_pool_size=%d\n",
states.vf_pool_size);
ret += sprintf(buf + ret, "vframe buf_free_num=%d\n",
states.buf_free_num);
ret += sprintf(buf + ret, "vframe buf_recycle_num=%d\n",
states.buf_recycle_num);
ret += sprintf(buf + ret, "vframe buf_avail_num=%d\n",
states.buf_avail_num);
} else {
ret += sprintf(buf + ret, "vframe no states\n");
}
return ret;
}
static struct class_attribute ppmgr_class_attrs[] = {
__ATTR(angle,
0644,
angle_read,
angle_write),
__ATTR(rect,
0644,
rect_read,
rect_write),
__ATTR(bypass,
0644,
bypass_read,
bypass_write),
__ATTR(disp,
0644,
disp_read,
disp_write),
__ATTR(orientation,
0664,
orientation_read,
orientation_write),
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
__ATTR(ppscaler,
0644,
ppscaler_read,
ppscaler_write),
__ATTR(ppscaler_rect,
0644,
ppscaler_rect_read,
ppscaler_rect_write),
#endif
__ATTR(vtarget,
0644,
receiver_read,
receiver_write),
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
__ATTR(ppmgr_3d_mode,
0644,
_3dmode_read,
_3dmode_write),
__ATTR(viewmode,
0644,
viewmode_read,
viewmode_write),
__ATTR(doublemode,
0644,
doublemode_read,
doublemode_write),
__ATTR(switchmode,
0644,
switchmode_read,
switchmode_write),
__ATTR(direction_3d,
0644,
direction_3d_read,
direction_3d_write),
__ATTR(scale_down,
0644,
scale_down_read,
scale_down_write),
__ATTR(depth,
0644,
read_depth,
write_depth),
__ATTR(view_mode,
0644,
read_view_mode,
write_view_mode),
__ATTR(vertical_sample,
0644,
read_vertical_sample,
write_vertical_sample),
__ATTR(scale_width,
0644,
read_scale_width,
write_scale_width),
__ATTR(axis,
0644,
cut_win_show,
cut_win_store),
#endif
__ATTR(platform_type,
0644,
platform_type_read,
platform_type_write),
__ATTR(mirror,
0644,
mirror_read,
mirror_write),
__ATTR_RO(ppmgr_vframe_states),
__ATTR(disable_prot,
0644,
disable_prot_show,
disable_prot_store),
__ATTR(tb_detect,
0644,
tb_detect_read,
tb_detect_write),
__ATTR(tb_detect_period,
0644,
tb_detect_period_read,
tb_detect_period_write),
__ATTR(tb_detect_len,
0644,
tb_detect_len_read,
tb_detect_len_write),
__ATTR(tb_detect_mute,
0644,
tb_detect_mute_read,
tb_detect_mute_write),
__ATTR(tb_status,
0644,
tb_status_read,
NULL),
__ATTR_NULL };
static struct class ppmgr_class = {.name = PPMGR_CLASS_NAME, .class_attrs =
ppmgr_class_attrs, };
struct class *init_ppmgr_cls(void)
{
int ret = 0;
ret = class_register(&ppmgr_class);
if (ret < 0) {
PPMGRDRV_ERR("error create ppmgr class\n");
return NULL;
}
return &ppmgr_class;
}
/***********************************************************************
*
* file op section.
*
************************************************************************/
int ppmgr_set_resource(unsigned long start, unsigned long end, struct device *p)
{
if (inited_ppmgr_num != 0) {
PPMGRDRV_ERR(
"We can't support the change resource at code running\n");
return -1;
}
ppmgr_dev_reg.mem_start = start;
ppmgr_dev_reg.mem_end = end;
ppmgr_dev_reg.cma_dev = p;
return 0;
}
static int ppmgr_open(struct inode *inode, struct file *file)
{
ppmgr_device.open_count++;
return 0;
}
static long ppmgr_ioctl(struct file *file, unsigned int cmd, ulong args)
{
void __user *argp = (void __user *)args;
int ret = 0;
#if 0
struct ge2d_context_s *context =
(struct ge2d_context_s *)filp->private_data;
config_para_t ge2d_config;
ge2d_para_t para;
int flag;
struct frame_info_t frame_info;
#endif
switch (cmd) {
#if 0
case PPMGR_IOC_CONFIG_FRAME:
copy_from_user(&frame_info, argp, sizeof(struct frame_info_t));
break;
#endif
case PPMGR_IOC_GET_ANGLE:
put_user(ppmgr_device.angle, (unsigned int *)argp);
break;
case PPMGR_IOC_SET_ANGLE:
ret = _ppmgr_angle_write(args);
break;
#if 0
case PPMGR_IOC_ENABLE_PP:
mode = (int)argp;
enum platform_type_t plarform_type;
plarform_type = get_platform_type();
if (plarform_type == PLATFORM_TV)
set_ppmgr_status(mode);
else
set_ppmgr_3dmode(mode);
break;
case PPMGR_IOC_VIEW_MODE:
mode = (int)argp;
set_ppmgr_viewmode(mode);
break;
case PPMGR_IOC_HOR_VER_DOUBLE:
flag = (int)argp;
mode = get_ppmgr_3dmode();
mode = (mode & (~PPMGR_3D_PROCESS_DOUBLE_TYPE))
| ((flag << PPMGR_3D_PROCESS_DOUBLE_TYPE_SHIFT)
& (PPMGR_3D_PROCESS_DOUBLE_TYPE));
set_ppmgr_3dmode(mode);
break;
case PPMGR_IOC_SWITCHMODE:
flag = (int)argp;
mode = get_ppmgr_3dmode();
if (flag)
mode = mode & PPMGR_3D_PROCESS_SWITCH_FLAG;
else
mode = mode & (~PPMGR_3D_PROCESS_SWITCH_FLAG);
set_ppmgr_3dmode(mode);
break;
case PPMGR_IOC_3D_DIRECTION:
flag = (int)argp;
/*mode = get_ppmgr_3dmode();*/
/* mode = (mode & (~PPMGR_3D_PROCESS_3D_ROTATE_DIRECTION_MASK))
* |((flag<<PPMGR_3D_PROCESS_3D_ROTATE_DIRECTION_VALUE_SHIFT)
* &(PPMGR_3D_PROCESS_3D_ROTATE_DIRECTION_MASK));
*/
/*set_ppmgr_3dmode(mode);*/
set_ppmgr_direction3d(flag);
break;
case PPMGR_IOC_3D_SCALE_DOWN:
mode = (int)argp;
set_ppmgr_scaledown(mode);
break;
#endif
default:
return -ENOIOCTLCMD;
}
return ret;
}
#ifdef CONFIG_COMPAT
static long ppmgr_compat_ioctl(struct file *filp,
unsigned int cmd, unsigned long args)
{
unsigned long ret;
args = (unsigned long)compat_ptr(args);
ret = ppmgr_ioctl(filp, cmd, args);
return ret;
}
#endif
static int ppmgr_release(struct inode *inode, struct file *file)
{
#ifdef CONFIG_ARCH_MESON
struct ge2d_context_s *context = (struct ge2d_context_s *)file
->private_data;
if (context && (destroy_ge2d_work_queue(context) == 0)) {
ppmgr_device.open_count--;
return 0;
}
PPMGRDRV_INFO("release one ppmgr device\n");
return -1;
#else
return 0;
#endif
}
#ifdef CONFIG_COMPAT
static long ppmgr_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long args);
#endif
/***********************************************************************
*
* file op initintg section.
*
************************************************************************/
static const struct file_operations ppmgr_fops = {
.owner = THIS_MODULE,
.open = ppmgr_open,
.unlocked_ioctl = ppmgr_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ppmgr_compat_ioctl,
#endif
.release = ppmgr_release, };
int init_ppmgr_device(void)
{
int ret = 0;
strcpy(ppmgr_device.name, "ppmgr");
ret = register_chrdev(0, ppmgr_device.name, &ppmgr_fops);
if (ret <= 0) {
PPMGRDRV_ERR("register ppmgr device error\n");
return ret;
}
ppmgr_device.major = ret;
ppmgr_device.dbg_enable = 0;
ppmgr_device.angle = 0;
ppmgr_device.bypass = 0;
ppmgr_device.videoangle = 0;
ppmgr_device.orientation = 0;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
ppmgr_device.ppscaler_flag = 0;
ppmgr_device.scale_h_start = 0;
ppmgr_device.scale_h_end = 0;
ppmgr_device.scale_v_start = 0;
ppmgr_device.scale_v_end = 0;
scaler_pos_reset = false;
#endif
ppmgr_device.receiver = 0;
ppmgr_device.receiver_format = (GE2D_FORMAT_M24_NV21
| GE2D_LITTLE_ENDIAN);
ppmgr_device.display_mode = 0;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
ppmgr_device.ppmgr_3d_mode = EXTERNAL_MODE_3D_DISABLE;
ppmgr_device.direction_3d = 0;
ppmgr_device.viewmode = VIEWMODE_NORMAL;
ppmgr_device.scale_down = 0;
#endif
ppmgr_device.mirror_flag = 0;
ppmgr_device.canvas_width = ppmgr_device.canvas_height = 0;
ppmgr_device.tb_detect = 0;
ppmgr_device.tb_detect_period = 0;
ppmgr_device.tb_detect_buf_len = 8;
ppmgr_device.tb_detect_init_mute = 0;
PPMGRDRV_INFO("ppmgr_dev major:%d\n", ret);
ppmgr_device.cla = init_ppmgr_cls();
if (ppmgr_device.cla == NULL)
return -1;
ppmgr_device.dev = device_create(ppmgr_device.cla, NULL,
MKDEV(ppmgr_device.major, 0),
NULL, ppmgr_device.name);
if (IS_ERR(ppmgr_device.dev)) {
PPMGRDRV_ERR("create ppmgr device error\n");
goto unregister_dev;
}
buff_change = 0;
ppmgr_register();
#if 0
if (ppmgr_buffer_init(0) < 0)
goto unregister_dev;
ppmgr_buffer_uninit();
#endif
/*if (start_vpp_task()<0) return -1;*/
ppmgr_device.use_prot = 1;
#if HAS_VPU_PROT
ppmgr_device.disable_prot = 0;
#else
ppmgr_device.disable_prot = 1;
#endif
ppmgr_device.global_angle = 0;
ppmgr_device.started = 0;
return 0;
unregister_dev: class_unregister(ppmgr_device.cla);
return -1;
}
int uninit_ppmgr_device(void)
{
stop_ppmgr_task();
if (ppmgr_device.cla) {
if (ppmgr_device.dev)
device_destroy(ppmgr_device.cla,
MKDEV(ppmgr_device.major, 0));
class_unregister(ppmgr_device.cla);
}
unregister_chrdev(ppmgr_device.major, ppmgr_device.name);
return 0;
}
/*******************************************************************
*
* interface for Linux driver
*
* ******************************************************************/
MODULE_AMLOG(AMLOG_DEFAULT_LEVEL, 0xff, LOG_LEVEL_DESC, LOG_MASK_DESC);
static struct platform_device *ppmgr_dev0;
/*static struct resource memobj;*/
/* for driver. */
static int ppmgr_driver_probe(struct platform_device *pdev)
{
s32 r;
PPMGRDRV_ERR("ppmgr_driver_probe called\n");
r = of_reserved_mem_device_init(&pdev->dev);
ppmgr_device.pdev = pdev;
init_ppmgr_device();
if (r == 0)
PPMGRDRV_INFO("ppmgr_probe done\n");
return r;
}
static int ppmgr_mem_device_init(struct reserved_mem *rmem, struct device *dev)
{
unsigned long start, end;
start = rmem->base;
end = rmem->base + rmem->size - 1;
PPMGRDRV_INFO("init ppmgr memsource %lx->%lx\n", start, end);
ppmgr_set_resource(start, end, dev);
if (rmem->size > 0) {
ppmgr_device.use_reserved = 1;
pr_warn("ppmgr use reserved memory\n");
}
return 0;
}
/* #ifdef CONFIG_USE_OF */
static const struct of_device_id amlogic_ppmgr_dt_match[] = {{.compatible =
"amlogic, ppmgr", }, {}, };
/* #else */
/* #define amlogic_ppmgr_dt_match NULL */
/* #endif */
static const struct reserved_mem_ops rmem_ppmgr_ops = {.device_init =
ppmgr_mem_device_init, };
#ifdef AMLOGIC_RMEM_MULTI_USER
static struct rmem_multi_user rmem_ppmgr_muser = {
.of_match_table = amlogic_ppmgr_dt_match,
.ops = &rmem_ppmgr_ops,
};
#endif
static int __init ppmgr_mem_setup(struct reserved_mem *rmem)
{
PPMGRDRV_DBG("ppmgr share mem setup\n");
ppmgr_device.use_reserved = 0;
#ifdef AMLOGIC_RMEM_MULTI_USER
of_add_rmem_multi_user(rmem, &rmem_ppmgr_muser);
#else
rmem->ops = &rmem_ppmgr_ops;
#endif
return 0;
}
static int ppmgr_drv_remove(struct platform_device *plat_dev)
{
/*struct rtc_device *rtc = platform_get_drvdata(plat_dev);*/
/*rtc_device_unregister(rtc);*/
/*device_remove_file(&plat_dev->dev, &dev_attr_irq);*/
uninit_ppmgr_device();
return 0;
}
/* general interface for a linux driver .*/
struct platform_driver ppmgr_drv = {
.probe = ppmgr_driver_probe,
.remove = ppmgr_drv_remove,
.driver = {
.name = "ppmgr",
.owner = THIS_MODULE,
.of_match_table = amlogic_ppmgr_dt_match,
}
};
static int __init
ppmgr_init_module(void)
{
int err;
PPMGRDRV_WARN("ppmgr module init func called\n");
amlog_level(LOG_LEVEL_HIGH, "ppmgr_init\n");
err = platform_driver_register(&ppmgr_drv);
if (err)
return err;
return err;
}
static void __exit
ppmgr_remove_module(void)
{
platform_device_put(ppmgr_dev0);
platform_driver_unregister(&ppmgr_drv);
amlog_level(LOG_LEVEL_HIGH, "ppmgr module removed.\n"); }
module_init(
ppmgr_init_module);
module_exit(ppmgr_remove_module);
RESERVEDMEM_OF_DECLARE(ppmgr, "amlogic, ppmgr-reserved-mem", ppmgr_mem_setup);
MODULE_DESCRIPTION("AMLOGIC ppmgr driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("aml-sh <kasin.li@amlogic.com>");