mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
gdc: add gdc driver
PD#165090: gdc add platform drivers base on the arm release. TODO use v4l2 m2m device driver rewrite. Change-Id: I1943f762041d005c17abd9b803b69ef68b08d290 Signed-off-by: Jiyu Yang <Jiyu.Yang@amlogic.com>
This commit is contained in:
@@ -14398,6 +14398,10 @@ AMLOGIC G12A Media codec io bus
|
||||
M: Nanxin Qin <nanxin.qin@amlogic.com>
|
||||
F: include/linux/amlogic/media/registers/regs/efuse_regs.h
|
||||
|
||||
AMLOGIC Geometric Distorition Correction
|
||||
M: Jiyu Yang <Jiyu.Yang@amlogic.com>
|
||||
F: drivers/amlogic/media/gdc/*
|
||||
|
||||
AMLOGIC G12A CVBS DRIVER
|
||||
M: Nian Jing <nian.jing@amlogic.com>
|
||||
F: drivers/amlogic/media/vout/cvbs/
|
||||
|
||||
@@ -1272,6 +1272,21 @@
|
||||
};
|
||||
};
|
||||
|
||||
gdc:gdc {
|
||||
#address-cells=<2>;
|
||||
#size-cells=<2>;
|
||||
status = "ok";
|
||||
compatible = "amlogic, g12b-gdc";
|
||||
reg = <0 0xFF950000 0 0x0000100
|
||||
0 0xFF63C16C 0 0x0000004
|
||||
0 0xFF63C100 0 0x0000004>;
|
||||
interrupts = <0 144 1>;
|
||||
interrupt-names = "GDC";
|
||||
clocks = <&clkc CLKID_GDC_CORE_CLK_COMP
|
||||
&clkc CLKID_GDC_AXI_CLK_COMP >;
|
||||
clock-names = "core","axi";
|
||||
};
|
||||
|
||||
mesonstream {
|
||||
compatible = "amlogic, codec, streambuf";
|
||||
dev_name = "mesonstream";
|
||||
|
||||
@@ -316,6 +316,7 @@ CONFIG_AMLOGIC_PIC_DEC=y
|
||||
CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y
|
||||
CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y
|
||||
CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y
|
||||
CONFIG_AMLOGIC_MEDIA_GDC=y
|
||||
CONFIG_AMLOGIC_DTV_DEMOD=y
|
||||
CONFIG_AMLOGIC_MMC=y
|
||||
CONFIG_AMLOGIC_NAND=y
|
||||
|
||||
@@ -61,6 +61,7 @@ source "drivers/amlogic/media/deinterlace/Kconfig"
|
||||
source "drivers/amlogic/media/vin/Kconfig"
|
||||
source "drivers/amlogic/media/video_processor/Kconfig"
|
||||
source "drivers/amlogic/media/enhancement/Kconfig"
|
||||
source "drivers/amlogic/media/gdc/Kconfig"
|
||||
endif
|
||||
source "drivers/amlogic/media/dtv_demod/Kconfig"
|
||||
endmenu
|
||||
|
||||
@@ -9,3 +9,4 @@ obj-$(CONFIG_AMLOGIC_MEDIA_VIN) += vin/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_VIDEO_PROCESSOR) += video_processor/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT) += enhancement/
|
||||
obj-$(CONFIG_AMLOGIC_DTV_DEMOD) += dtv_demod/
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_GDC) += gdc/
|
||||
|
||||
8
drivers/amlogic/media/gdc/Kconfig
Normal file
8
drivers/amlogic/media/gdc/Kconfig
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# gdc driver configuration
|
||||
#
|
||||
config AMLOGIC_MEDIA_GDC
|
||||
bool "Amlogic gdc driver"
|
||||
default n
|
||||
help
|
||||
Select to enable gdc driver.
|
||||
18
drivers/amlogic/media/gdc/Makefile
Normal file
18
drivers/amlogic/media/gdc/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
FW_SRC := src/fw_lib/acamera_gdc.c \
|
||||
src/platform/system_gdc_io.c \
|
||||
src/platform/system_log.c \
|
||||
app/gdc_main.c \
|
||||
app/gdc_module.c
|
||||
|
||||
FW_SRC_OBJ := $(FW_SRC:.c=.o)
|
||||
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_GDC) += $(FW_SRC_OBJ)
|
||||
|
||||
PWD=$(src)
|
||||
ccflags-y +=-I$(PWD)/app -I$(PWD)/inc
|
||||
ccflags-y +=-I$(PWD)/inc/api -I$(PWD)/inc/gdc -I$(PWD)/inc/sys
|
||||
ccflags-y +=-I$(PWD)/src/platform -I$(PWD)/src/fw_lib
|
||||
ccflags-y += -Idrivers/amlogic/media/common/ion_dev/
|
||||
ccflags-y += -Idrivers/staging/android/
|
||||
|
||||
ccflags-y += -Wno-declaration-after-statement
|
||||
63
drivers/amlogic/media/gdc/app/gdc_main.c
Normal file
63
drivers/amlogic/media/gdc/app/gdc_main.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* drivers/amlogic/media/gdc/app/gdc_main.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 "system_log.h"
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
//gdc api functions
|
||||
#include "gdc_api.h"
|
||||
|
||||
irqreturn_t interrupt_handler_next(int irq, void *param)
|
||||
{
|
||||
//handle the start of frame with gdc_process
|
||||
struct gdc_settings *gdc_settings = (struct gdc_settings *)param;
|
||||
|
||||
gdc_get_frame(gdc_settings);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int gdc_run(struct gdc_settings *g)
|
||||
{
|
||||
|
||||
gdc_stop(g);
|
||||
|
||||
LOG(LOG_INFO, "Done gdc load..\n");
|
||||
|
||||
//initialise the gdc by the first configuration
|
||||
if (gdc_init(g) != 0) {
|
||||
LOG(LOG_ERR, "Failed to initialise GDC block");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG(LOG_INFO, "Done gdc config..\n");
|
||||
|
||||
//start gdc process with input address for y and uv planes
|
||||
if (g->gdc_config.format == NV12) {
|
||||
gdc_process(g,
|
||||
(uint32_t)g->y_base_addr,
|
||||
(uint32_t)g->uv_base_addr);
|
||||
} else {
|
||||
gdc_process_yuv420p(g, (uint32_t)g->y_base_addr,
|
||||
(uint32_t)g->u_base_addr,
|
||||
(uint32_t)g->v_base_addr);
|
||||
}
|
||||
LOG(LOG_DEBUG, "call gdc process\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
318
drivers/amlogic/media/gdc/app/gdc_module.c
Normal file
318
drivers/amlogic/media/gdc/app/gdc_module.c
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* drivers/amlogic/media/gdc/app/gdc_module.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/platform_device.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uio_driver.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <meson_ion.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/of_address.h>
|
||||
#include <api/gdc_api.h>
|
||||
#include "system_log.h"
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/semaphore.h>
|
||||
//gdc configuration sequence
|
||||
#include "gdc_config.h"
|
||||
|
||||
struct meson_gdc_dev_t *g_gdc_dev;
|
||||
|
||||
static const struct of_device_id gdc_dt_match[] = {
|
||||
{.compatible = "amlogic, g12b-gdc"},
|
||||
{} };
|
||||
|
||||
MODULE_DEVICE_TABLE(of, gdc_dt_match);
|
||||
|
||||
//////
|
||||
static int meson_gdc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct meson_gdc_dev_t *gdc_dev = g_gdc_dev;
|
||||
struct platform_device *pdev = gdc_dev->pdev;
|
||||
struct mgdc_fh_s *fh = NULL;
|
||||
char ion_client_name[32];
|
||||
int rc = 0;
|
||||
|
||||
fh = devm_kzalloc(&pdev->dev, sizeof(*fh), GFP_KERNEL);
|
||||
if (fh == NULL) {
|
||||
LOG(LOG_DEBUG, "devm alloc failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
get_task_comm(fh->task_comm, current);
|
||||
LOG(LOG_DEBUG, "%s, %d, call from %s\n",
|
||||
__func__, __LINE__, fh->task_comm);
|
||||
|
||||
file->private_data = fh;
|
||||
snprintf(ion_client_name, sizeof(fh->task_comm),
|
||||
"gdc-%s", fh->task_comm);
|
||||
if (!fh->ion_client)
|
||||
fh->ion_client = meson_ion_client_create(-1, ion_client_name);
|
||||
|
||||
fh->gdev = gdc_dev;
|
||||
init_waitqueue_head(&fh->irq_queue);
|
||||
|
||||
rc = devm_request_irq(&pdev->dev, gdc_dev->irq, interrupt_handler_next,
|
||||
IRQF_SHARED, "gdc", &fh->gs);
|
||||
if (rc)
|
||||
LOG(LOG_DEBUG, "cannot create irq func gdc\n");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int meson_gdc_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct mgdc_fh_s *fh = file->private_data;
|
||||
struct meson_gdc_dev_t *gdc_dev = fh->gdev;
|
||||
struct platform_device *pdev = gdc_dev->pdev;
|
||||
|
||||
LOG(LOG_DEBUG, "%s, %d\n", __func__, __LINE__);
|
||||
if (fh->ion_client) {
|
||||
ion_client_destroy(fh->ion_client);
|
||||
fh->ion_client = NULL;
|
||||
}
|
||||
|
||||
devm_free_irq(&pdev->dev, gdc_dev->irq, &fh->gs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long meson_gdc_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
size_t len;
|
||||
struct mgdc_fh_s *fh = file->private_data;
|
||||
struct gdc_settings *gs = &fh->gs;
|
||||
struct gdc_config *gc = &gs->gdc_config;
|
||||
long ret = 0;
|
||||
ion_phys_addr_t addr;
|
||||
void __user *argp = (void __user *)arg;
|
||||
|
||||
gs->fh = fh;
|
||||
|
||||
switch (cmd) {
|
||||
case GDC_PROCESS:
|
||||
ret = copy_from_user(gs, argp, sizeof(*gs));
|
||||
if (ret < 0)
|
||||
LOG(LOG_DEBUG, "copy from user failed\n");
|
||||
|
||||
LOG(LOG_DEBUG, "sizeof(gs)=%ld, magic=%d\n",
|
||||
sizeof(*gs), gs->magic);
|
||||
|
||||
//configure gdc config, buffer address and resolution
|
||||
ret = meson_ion_share_fd_to_phys(fh->ion_client,
|
||||
gs->out_fd, &addr, &len);
|
||||
|
||||
gs->buffer_addr = addr;
|
||||
gs->buffer_size = len;
|
||||
|
||||
if (ret < 0)
|
||||
LOG(LOG_DEBUG, "import out fd %d failed\n", gs->out_fd);
|
||||
gs->base_gdc = 0;
|
||||
gs->current_addr = gs->buffer_addr;
|
||||
|
||||
ret = meson_ion_share_fd_to_phys(fh->ion_client,
|
||||
gc->config_addr, &addr, &len);
|
||||
|
||||
gc->config_addr = addr;
|
||||
|
||||
ret = meson_ion_share_fd_to_phys(fh->ion_client,
|
||||
gs->in_fd, &addr, &len);
|
||||
if (gc->format == NV12) {
|
||||
gs->y_base_addr = addr;
|
||||
gs->uv_base_addr = addr +
|
||||
gc->input_y_stride * gc->input_height;
|
||||
} else if (gc->format == YV12) {
|
||||
gs->y_base_addr = addr;
|
||||
gs->u_base_addr = addr
|
||||
+ gc->input_y_stride * gc->input_height;
|
||||
|
||||
gs->v_base_addr = gs->u_base_addr +
|
||||
gc->input_c_stride * gc->input_height / 2;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
LOG(LOG_DEBUG, "import in fd %d failed\n", gs->in_fd);
|
||||
|
||||
gs->fh = fh;
|
||||
ret = gdc_run(gs);
|
||||
if (ret < 0)
|
||||
LOG(LOG_DEBUG, "gdc process ret = %ld\n", ret);
|
||||
|
||||
ret = wait_event_interruptible_timeout(fh->irq_queue,
|
||||
(gdc_busy_read() == 0),
|
||||
msecs_to_jiffies(30));
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_info("unsupported cmd 0x%x\n", cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations meson_gdc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = meson_gdc_open,
|
||||
.release = meson_gdc_release,
|
||||
.unlocked_ioctl = meson_gdc_ioctl,
|
||||
.compat_ioctl = meson_gdc_ioctl,
|
||||
};
|
||||
|
||||
static struct miscdevice meson_gdc_dev = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "gdc",
|
||||
.fops = &meson_gdc_fops,
|
||||
};
|
||||
|
||||
static ssize_t gdc_reg_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
int i;
|
||||
|
||||
len += sprintf(buf+len, "gdc adapter register below\n");
|
||||
for (i = 0; i <= 0xff; i += 4) {
|
||||
len += sprintf(buf+len, "\t[0xff950000 + 0x%08x, 0x%-8x\n",
|
||||
i, system_gdc_read_32(i));
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t gdc_reg_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
LOG(LOG_DEBUG, "%s, %d\n", __func__, __LINE__);
|
||||
return len;
|
||||
}
|
||||
static DEVICE_ATTR(gdc_reg, 0554, gdc_reg_show, gdc_reg_store);
|
||||
|
||||
static ssize_t firmware1_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
LOG(LOG_DEBUG, "%s, %d\n", __func__, __LINE__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ssize_t firmware1_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
LOG(LOG_DEBUG, "%s, %d\n", __func__, __LINE__);
|
||||
//gdc_fw_init();
|
||||
return 1;
|
||||
}
|
||||
static DEVICE_ATTR(firmware1, 0664, firmware1_show, firmware1_store);
|
||||
|
||||
|
||||
static int gdc_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *gdc_res;
|
||||
struct meson_gdc_dev_t *gdc_dev = NULL;
|
||||
void *clk_cntl = NULL;
|
||||
void *pd_cntl = NULL;
|
||||
uint32_t reg_value = 0;
|
||||
|
||||
// Initialize irq
|
||||
gdc_res = platform_get_resource(pdev,
|
||||
IORESOURCE_MEM, 0);
|
||||
if (!gdc_res) {
|
||||
LOG(LOG_ERR, "Error, no IORESOURCE_MEM DT!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (init_gdc_io(pdev->dev.of_node) != 0) {
|
||||
LOG(LOG_ERR, "Error on mapping gdc memory!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
device_create_file(&pdev->dev, &dev_attr_gdc_reg);
|
||||
device_create_file(&pdev->dev, &dev_attr_firmware1);
|
||||
|
||||
gdc_dev = devm_kzalloc(&pdev->dev, sizeof(*gdc_dev),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (gdc_dev == NULL) {
|
||||
LOG(LOG_DEBUG, "devm alloc gdc dev failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
gdc_dev->pdev = pdev;
|
||||
spin_lock_init(&gdc_dev->slock);
|
||||
|
||||
gdc_dev->irq = platform_get_irq(pdev, 0);
|
||||
if (gdc_dev->irq < 0) {
|
||||
LOG(LOG_DEBUG, "cannot find irq for gdc\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
gdc_dev->clk_core = devm_clk_get(&pdev->dev, "core");
|
||||
rc = clk_set_rate(gdc_dev->clk_core, 800000000);
|
||||
|
||||
gdc_dev->clk_axi = devm_clk_get(&pdev->dev, "axi");
|
||||
rc = clk_set_rate(gdc_dev->clk_axi, 800000000);
|
||||
#else
|
||||
clk_cntl = of_iomap(pdev->dev.of_node, 1);
|
||||
iowrite32((3<<25)|(1<<24)|(0<<16)|(3<<9)|(1<<8)|(0<<0), clk_cntl);
|
||||
pd_cntl = of_iomap(pdev->dev.of_node, 2);
|
||||
reg_value = ioread32(pd_cntl);
|
||||
LOG(LOG_DEBUG, "pd_cntl=%x\n", reg_value);
|
||||
reg_value = reg_value & (~(3<<18));
|
||||
LOG(LOG_DEBUG, "pd_cntl=%x\n", reg_value);
|
||||
iowrite32(reg_value, pd_cntl);
|
||||
#endif
|
||||
|
||||
g_gdc_dev = gdc_dev;
|
||||
|
||||
return misc_register(&meson_gdc_dev);
|
||||
}
|
||||
|
||||
static int gdc_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
device_remove_file(&pdev->dev, &dev_attr_gdc_reg);
|
||||
device_remove_file(&pdev->dev, &dev_attr_firmware1);
|
||||
|
||||
misc_deregister(&meson_gdc_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver gdc_platform_driver = {
|
||||
.driver = {
|
||||
.name = "gdc",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = gdc_dt_match,
|
||||
},
|
||||
.probe = gdc_platform_probe,
|
||||
.remove = gdc_platform_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(gdc_platform_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Amlogic Multimedia");
|
||||
174
drivers/amlogic/media/gdc/inc/api/gdc_api.h
Normal file
174
drivers/amlogic/media/gdc/inc/api/gdc_api.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* drivers/amlogic/media/gdc/inc/api/gdc_api.h
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GDC_API_H__
|
||||
#define __GDC_API_H__
|
||||
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#define NV12 1
|
||||
#define YV12 2
|
||||
|
||||
// each configuration addresses and size
|
||||
struct gdc_config {
|
||||
uint32_t format;
|
||||
uint32_t config_addr; //gdc config address
|
||||
uint32_t config_size; //gdc config size in 32bit
|
||||
uint32_t input_width; //gdc input width resolution
|
||||
uint32_t input_height; //gdc input height resolution
|
||||
uint32_t input_y_stride; //gdc input y stride resolution
|
||||
uint32_t input_c_stride; //gdc input uv stride
|
||||
uint32_t output_width; //gdc output width resolution
|
||||
uint32_t output_height; //gdc output height resolution
|
||||
uint32_t output_y_stride; //gdc output y stride
|
||||
uint32_t output_c_stride; //gdc output uv stride
|
||||
};
|
||||
|
||||
// overall gdc settings and state
|
||||
struct gdc_settings {
|
||||
uint32_t magic;
|
||||
//writing/reading to gdc base address, currently not read by api
|
||||
uint32_t base_gdc;
|
||||
//array of gdc configuration and sizes
|
||||
struct gdc_config gdc_config;
|
||||
//update this index for new config
|
||||
//int gdc_config_total;
|
||||
//start memory to write gdc output framse
|
||||
uint32_t buffer_addr;
|
||||
//size of memory output frames to determine
|
||||
//if it is enough and can do multiple write points
|
||||
uint32_t buffer_size;
|
||||
//current output address of gdc
|
||||
uint32_t current_addr;
|
||||
//set when expecting an interrupt from gdc
|
||||
int32_t is_waiting_gdc;
|
||||
|
||||
int32_t in_fd; //input buffer's share fd
|
||||
int32_t out_fd; //output buffer's share fd
|
||||
|
||||
//input address for y and u, v planes
|
||||
uint32_t y_base_addr;
|
||||
union {
|
||||
uint32_t uv_base_addr;
|
||||
uint32_t u_base_addr;
|
||||
};
|
||||
uint32_t v_base_addr;
|
||||
//opaque address in ddr added with offset to
|
||||
//write the gdc config sequence
|
||||
void *ddr_mem;
|
||||
//when inititialised this callback will be called
|
||||
//to update frame buffer addresses and offsets
|
||||
void (*get_frame_buffer)(uint32_t y_base_addr,
|
||||
uint32_t uv_base_addr,
|
||||
uint32_t y_line_offset,
|
||||
uint32_t uv_line_offset);
|
||||
void *fh;
|
||||
};
|
||||
|
||||
#define GDC_IOC_MAGIC 'G'
|
||||
#define GDC_PROCESS _IOW(GDC_IOC_MAGIC, 0x00, struct gdc_settings)
|
||||
#define GDC_PROCESS_NO_BLOCK _IOW(GDC_IOC_MAGIC, 0x01, struct gdc_settings)
|
||||
/**
|
||||
* Configure the output gdc configuration
|
||||
*
|
||||
* address/size and buffer address/size; and resolution.
|
||||
*
|
||||
* More than one gdc settings can be accessed by index to a gdc_config_t.
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
* @param gdc_config_num - selects the current gdc config to be applied
|
||||
*
|
||||
* @return 0 - success
|
||||
* -1 - fail.
|
||||
*/
|
||||
int gdc_init(struct gdc_settings *gdc_settings);
|
||||
/**
|
||||
* This function stops the gdc block
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
*
|
||||
*/
|
||||
void gdc_stop(struct gdc_settings *gdc_settings);
|
||||
|
||||
/**
|
||||
* This function starts the gdc block
|
||||
*
|
||||
* Writing 0->1 transition is necessary for trigger
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
*
|
||||
*/
|
||||
void gdc_start(struct gdc_settings *gdc_settings);
|
||||
|
||||
/**
|
||||
* This function points gdc to
|
||||
*
|
||||
* its input resolution and yuv address and offsets
|
||||
*
|
||||
* Shown inputs to GDC are Y and UV plane address and offsets
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
* @param active_width - input width resolution
|
||||
* @param active_height - input height resolution
|
||||
* @param y_base_addr - input Y base address
|
||||
* @param uv_base_addr - input UV base address
|
||||
* @param y_line_offset - input Y line buffer offset
|
||||
* @param uv_line_offset- input UV line buffer offer
|
||||
*
|
||||
* @return 0 - success
|
||||
* -1 - no interrupt from GDC.
|
||||
*/
|
||||
int gdc_process(struct gdc_settings *gdc_settings,
|
||||
uint32_t y_base_addr,
|
||||
uint32_t uv_base_addr);
|
||||
int gdc_process_yuv420p(struct gdc_settings *gdc_settings,
|
||||
uint32_t y_base_addr,
|
||||
uint32_t u_base_addr,
|
||||
uint32_t v_base_addr);
|
||||
/**
|
||||
* This function gets the GDC output frame addresses
|
||||
*
|
||||
* and offsets and updates the frame buffer via callback
|
||||
*
|
||||
* if it is available Shown ouputs to GDC are
|
||||
*
|
||||
* Y and UV plane address and offsets
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
*
|
||||
* @return 0 - success
|
||||
* -1 - unexpected interrupt from GDC.
|
||||
*/
|
||||
int gdc_get_frame(struct gdc_settings *gdc_settings);
|
||||
|
||||
/**
|
||||
* This function points gdc to its input resolution
|
||||
*
|
||||
* and yuv address and offsets
|
||||
*
|
||||
* Shown inputs to GDC are Y and UV plane address and offsets
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
*
|
||||
* @return 0 - success
|
||||
* -1 - no interrupt from GDC.
|
||||
*/
|
||||
int gdc_run(struct gdc_settings *g);
|
||||
|
||||
int32_t init_gdc_io(struct device_node *dn);
|
||||
|
||||
#endif
|
||||
1890
drivers/amlogic/media/gdc/inc/gdc/gdc_config.h
Normal file
1890
drivers/amlogic/media/gdc/inc/gdc/gdc_config.h
Normal file
File diff suppressed because it is too large
Load Diff
44
drivers/amlogic/media/gdc/inc/sys/system_gdc_io.h
Normal file
44
drivers/amlogic/media/gdc/inc/sys/system_gdc_io.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* drivers/amlogic/media/gdc/inc/sys/system_gdc_io.h
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SYSTEM_GDC_IO_H__
|
||||
#define __SYSTEM_GDC_IO_H__
|
||||
|
||||
/**
|
||||
* Read 32 bit word from gdc memory
|
||||
*
|
||||
* This function returns a 32 bits word from GDC memory with a given offset.
|
||||
*
|
||||
* @param addr - the offset in GDC memory to read 32 bits word.
|
||||
*
|
||||
* @return 32 bits memory value
|
||||
*/
|
||||
uint32_t system_gdc_read_32(uint32_t addr);
|
||||
|
||||
|
||||
/**
|
||||
* Write 32 bits word to gdc memory
|
||||
*
|
||||
* This function writes a 32 bits word to GDC memory with a given offset.
|
||||
*
|
||||
* @param addr - the offset in GDC memory to write data.
|
||||
* @param data - data to be written
|
||||
*/
|
||||
void system_gdc_write_32(uint32_t addr, uint32_t data);
|
||||
|
||||
|
||||
#endif /* __SYSTEM_GDC_IO_H__ */
|
||||
55
drivers/amlogic/media/gdc/inc/sys/system_log.h
Normal file
55
drivers/amlogic/media/gdc/inc/sys/system_log.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* drivers/amlogic/media/gdc/inc/sys/system_log.h
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SYSTEM_LOG_H__
|
||||
#define __SYSTEM_LOG_H__
|
||||
|
||||
//changeable logs
|
||||
#include <linux/kernel.h>
|
||||
#define FW_LOG_LEVEL LOG_MAX
|
||||
|
||||
enum log_level_e {
|
||||
LOG_NOTHING,
|
||||
LOG_EMERG,
|
||||
LOG_ALERT,
|
||||
LOG_CRIT,
|
||||
LOG_ERR,
|
||||
LOG_WARNING,
|
||||
LOG_NOTICE,
|
||||
LOG_INFO,
|
||||
LOG_DEBUG,
|
||||
LOG_IRQ,
|
||||
LOG_MAX
|
||||
};
|
||||
|
||||
extern const char *const gdc_log_level[LOG_MAX];
|
||||
|
||||
#define FILE (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
#if 1
|
||||
#define LOG(level, fmt, arg...) \
|
||||
do { \
|
||||
if ((level) <= FW_LOG_LEVEL) \
|
||||
trace_printk("%s: %s(%d) %s: " fmt "\n",\
|
||||
FILE, __func__, __LINE__, \
|
||||
gdc_log_level[level], ## arg); \
|
||||
} while (0)
|
||||
#else
|
||||
#define LOG(...)
|
||||
#endif
|
||||
|
||||
#endif // __SYSTEM_LOG_H__
|
||||
280
drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c
Normal file
280
drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.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.
|
||||
*
|
||||
*/
|
||||
|
||||
//needed for gdc/gdc configuration
|
||||
#include <linux/wait.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
//data types and prototypes
|
||||
#include "gdc_api.h"
|
||||
#include "system_log.h"
|
||||
#include "gdc_config.h"
|
||||
|
||||
|
||||
/**
|
||||
* Configure the output gdc configuration address/size
|
||||
*
|
||||
* and buffer address/size; and resolution.
|
||||
*
|
||||
* More than one gdc settings can be accessed by index to a gdc_config_t.
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
* @param gdc_config_num - selects the current gdc config to be applied
|
||||
*
|
||||
* @return 0 - success
|
||||
* -1 - fail.
|
||||
*/
|
||||
int gdc_init(struct gdc_settings *gdc_settings)
|
||||
{
|
||||
|
||||
gdc_settings->is_waiting_gdc = 0;
|
||||
gdc_settings->current_addr = gdc_settings->buffer_addr;
|
||||
|
||||
if ((gdc_settings->gdc_config.output_width == 0)
|
||||
|| (gdc_settings->gdc_config.output_height == 0)) {
|
||||
LOG(LOG_ERR, "Wrong GDC output resolution.\n");
|
||||
return -1;
|
||||
}
|
||||
//stop gdc
|
||||
gdc_start_flag_write(0);
|
||||
//set the configuration address and size to the gdc block
|
||||
gdc_config_addr_write(gdc_settings->gdc_config.config_addr);
|
||||
gdc_config_size_write(gdc_settings->gdc_config.config_size);
|
||||
|
||||
//set the gdc output resolution
|
||||
gdc_dataout_width_write(gdc_settings->gdc_config.output_width);
|
||||
gdc_dataout_height_write(gdc_settings->gdc_config.output_height);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function stops the gdc block
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
*
|
||||
*/
|
||||
void gdc_stop(struct gdc_settings *gdc_settings)
|
||||
{
|
||||
gdc_settings->is_waiting_gdc = 0;
|
||||
gdc_start_flag_write(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function starts the gdc block
|
||||
*
|
||||
* Writing 0->1 transition is necessary for trigger
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
*
|
||||
*/
|
||||
void gdc_start(struct gdc_settings *gdc_settings)
|
||||
{
|
||||
gdc_start_flag_write(0); //do a stop for sync
|
||||
gdc_start_flag_write(1);
|
||||
gdc_settings->is_waiting_gdc = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function points gdc to its input resolution
|
||||
*
|
||||
* and yuv address and offsets
|
||||
*
|
||||
* Shown inputs to GDC are Y and UV plane address and offsets
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
* @param active_width - input width resolution
|
||||
* @param active_height - input height resolution
|
||||
* @param y_base_addr - input Y base address
|
||||
* @param uv_base_addr - input UV base address
|
||||
* @param y_line_offset - input Y line buffer offset
|
||||
* @param uv_line_offset- input UV line buffer offer
|
||||
*
|
||||
* @return 0 - success
|
||||
* -1 - no interrupt from GDC.
|
||||
*/
|
||||
int gdc_process(struct gdc_settings *gdc_settings,
|
||||
uint32_t y_base_addr, uint32_t uv_base_addr)
|
||||
{
|
||||
uint32_t gdc_out_base_addr = gdc_settings->current_addr;
|
||||
uint32_t active_width = gdc_settings->gdc_config.output_width;
|
||||
uint32_t active_height = gdc_settings->gdc_config.output_height;
|
||||
uint32_t y_line_offset = active_width; //420 format
|
||||
uint32_t uv_line_offset = active_width; //420 format
|
||||
|
||||
if (gdc_settings->is_waiting_gdc) {
|
||||
gdc_start_flag_write(0);
|
||||
LOG(LOG_CRIT, "No interrupt Still waiting...\n");
|
||||
gdc_start_flag_write(1);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG(LOG_DEBUG, "starting GDC process.\n");
|
||||
|
||||
gdc_datain_width_write(active_width);
|
||||
gdc_datain_height_write(active_height);
|
||||
//input y plane
|
||||
gdc_data1in_addr_write(y_base_addr);
|
||||
gdc_data1in_line_offset_write(y_line_offset);
|
||||
|
||||
//input uv plane
|
||||
gdc_data2in_addr_write(uv_base_addr);
|
||||
gdc_data2in_line_offset_write(uv_line_offset);
|
||||
|
||||
//gdc y output
|
||||
gdc_data1out_addr_write(gdc_out_base_addr);
|
||||
gdc_data1out_line_offset_write(y_line_offset);
|
||||
|
||||
//gdc uv output
|
||||
gdc_out_base_addr += active_height * y_line_offset;
|
||||
gdc_data2out_addr_write(gdc_out_base_addr);
|
||||
gdc_data2out_line_offset_write(uv_line_offset);
|
||||
|
||||
gdc_start(gdc_settings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function points gdc to its input resolution
|
||||
*
|
||||
* and yuv address and offsets
|
||||
*
|
||||
* Shown inputs to GDC are Y and UV plane address and offsets
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
* @param active_width - input width resolution
|
||||
* @param active_height - input height resolution
|
||||
* @param y_base_addr - input Y base address
|
||||
* @param uv_base_addr - input UV base address
|
||||
* @param y_line_offset - input Y line buffer offset
|
||||
* @param uv_line_offset- input UV line buffer offer
|
||||
*
|
||||
* @return 0 - success
|
||||
* -1 - no interrupt from GDC.
|
||||
*/
|
||||
int gdc_process_yuv420p(struct gdc_settings *gdc_settings,
|
||||
uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr)
|
||||
{
|
||||
struct gdc_config *gc = &gdc_settings->gdc_config;
|
||||
uint32_t gdc_out_base_addr = gdc_settings->current_addr;
|
||||
uint32_t input_width = gc->input_width;
|
||||
uint32_t input_height = gc->input_height;
|
||||
uint32_t input_stride = gc->input_y_stride;
|
||||
uint32_t input_u_stride = gc->input_c_stride;
|
||||
uint32_t input_v_stride = gc->input_c_stride;
|
||||
|
||||
LOG(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_settings->is_waiting_gdc);
|
||||
if (gdc_settings->is_waiting_gdc) {
|
||||
gdc_start_flag_write(0);
|
||||
LOG(LOG_CRIT, "No interrupt Still waiting...\n");
|
||||
gdc_start_flag_write(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/////
|
||||
LOG(LOG_DEBUG, "starting GDC process.\n");
|
||||
|
||||
//already set in gdc_init
|
||||
//uint32_t output_width = gc->output_width;
|
||||
uint32_t output_height = gc->output_height;
|
||||
uint32_t output_stride = gc->output_y_stride;
|
||||
uint32_t output_u_stride = gc->output_c_stride;
|
||||
uint32_t output_v_stride = gc->output_c_stride;
|
||||
|
||||
gdc_datain_width_write(input_width);
|
||||
gdc_datain_height_write(input_height);
|
||||
//input y plane
|
||||
gdc_data1in_addr_write(y_base_addr);
|
||||
gdc_data1in_line_offset_write(input_stride);
|
||||
|
||||
//input u plane
|
||||
gdc_data2in_addr_write(u_base_addr);
|
||||
gdc_data2in_line_offset_write(input_u_stride);
|
||||
|
||||
//input v plane
|
||||
gdc_data3in_addr_write(v_base_addr);
|
||||
gdc_data3in_line_offset_write(input_v_stride);
|
||||
|
||||
//gdc y output
|
||||
gdc_data1out_addr_write(gdc_out_base_addr);
|
||||
gdc_data1out_line_offset_write(output_stride);
|
||||
|
||||
//gdc u output
|
||||
gdc_out_base_addr += output_height * output_stride;
|
||||
gdc_data2out_addr_write(gdc_out_base_addr);
|
||||
gdc_data2out_line_offset_write(output_u_stride);
|
||||
|
||||
//gdc v output
|
||||
gdc_out_base_addr += output_height * output_u_stride / 2;
|
||||
gdc_data3out_addr_write(gdc_out_base_addr);
|
||||
gdc_data3out_line_offset_write(output_v_stride);
|
||||
gdc_start(gdc_settings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function gets the GDC output frame addresses
|
||||
*
|
||||
* and offsets and updates the frame buffer via callback
|
||||
*
|
||||
* if it is available Shown ouputs to GDC are
|
||||
*
|
||||
* Y and UV plane address and offsets
|
||||
*
|
||||
* @param gdc_settings - overall gdc settings and state
|
||||
*
|
||||
* @return 0 - success
|
||||
* -1 - unexpected interrupt from GDC.
|
||||
*/
|
||||
int gdc_get_frame(struct gdc_settings *gdc_settings)
|
||||
{
|
||||
struct mgdc_fh_s *fh = gdc_settings->fh;
|
||||
uint32_t y;
|
||||
uint32_t y_offset;
|
||||
uint32_t uv;
|
||||
uint32_t uv_offset;
|
||||
|
||||
if (!gdc_settings->is_waiting_gdc) {
|
||||
LOG(LOG_CRIT, "Unexpected interrupt from GDC.\n");
|
||||
return -1;
|
||||
}
|
||||
////
|
||||
|
||||
wake_up_interruptible(&fh->irq_queue);
|
||||
|
||||
//pass the frame buffer parameters if callback is available
|
||||
if (gdc_settings->get_frame_buffer) {
|
||||
y = gdc_data1out_addr_read();
|
||||
y_offset = gdc_data1out_line_offset_read();
|
||||
uv = gdc_data2out_addr_read();
|
||||
uv_offset = gdc_data2out_line_offset_read();
|
||||
|
||||
gdc_settings->get_frame_buffer(y,
|
||||
uv, y_offset, uv_offset);
|
||||
}
|
||||
//done of the current frame and stop gdc block
|
||||
gdc_stop(gdc_settings);
|
||||
//spin_unlock_irqrestore(&gdev->slock, flags);
|
||||
return 0;
|
||||
}
|
||||
66
drivers/amlogic/media/gdc/src/platform/system_gdc_io.c
Normal file
66
drivers/amlogic/media/gdc/src/platform/system_gdc_io.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* drivers/amlogic/media/gdc/src/platform/system_gdc_io.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 "system_log.h"
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
static void *p_hw_base;
|
||||
|
||||
int32_t init_gdc_io(struct device_node *dn)
|
||||
{
|
||||
p_hw_base = of_iomap(dn, 0);
|
||||
|
||||
pr_info("reg base = %p\n", p_hw_base);
|
||||
if (!p_hw_base) {
|
||||
LOG(LOG_DEBUG, "failed to map register, %p\n", p_hw_base);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void close_gdc_io(struct device_node *dn)
|
||||
{
|
||||
LOG(LOG_DEBUG, "IO functionality has been closed");
|
||||
}
|
||||
|
||||
uint32_t system_gdc_read_32(uint32_t addr)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
if (p_hw_base == NULL)
|
||||
LOG(LOG_ERR, "Failed to base address %d\n", addr);
|
||||
|
||||
result = ioread32(p_hw_base + addr);
|
||||
LOG(LOG_DEBUG, "r [0x%04x]= %08x\n", addr, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void system_gdc_write_32(uint32_t addr, uint32_t data)
|
||||
{
|
||||
if (p_hw_base == NULL)
|
||||
LOG(LOG_ERR, "Failed to write %d to addr %d\n", data, addr);
|
||||
|
||||
void *ptr = (void *)(p_hw_base + addr);
|
||||
|
||||
iowrite32(data, ptr);
|
||||
LOG(LOG_DEBUG, "w [0x%04x]= %08x\n", addr, data);
|
||||
}
|
||||
21
drivers/amlogic/media/gdc/src/platform/system_log.c
Normal file
21
drivers/amlogic/media/gdc/src/platform/system_log.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* drivers/amlogic/media/gdc/src/platform/system_log.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 "system_log.h"
|
||||
const char *const gdc_log_level[LOG_MAX] = {"",
|
||||
"EMERG", "ALERT", "CRIT", "ERR", "WARNING",
|
||||
"NOTICE", "INFO", "LOG_DEBUG", "LOG_IRQ"};
|
||||
Reference in New Issue
Block a user