From d70c59eeb629ce854364c15c452f258ca6ae9b92 Mon Sep 17 00:00:00 2001 From: Jiyu Yang Date: Wed, 6 Jun 2018 21:20:34 +0800 Subject: [PATCH] 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 --- MAINTAINERS | 4 + arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 15 + arch/arm64/configs/meson64_defconfig | 1 + drivers/amlogic/media/Kconfig | 1 + drivers/amlogic/media/Makefile | 1 + drivers/amlogic/media/gdc/Kconfig | 8 + drivers/amlogic/media/gdc/Makefile | 18 + drivers/amlogic/media/gdc/app/gdc_main.c | 63 + drivers/amlogic/media/gdc/app/gdc_module.c | 318 ++++ drivers/amlogic/media/gdc/inc/api/gdc_api.h | 174 ++ drivers/amlogic/media/gdc/inc/gdc/gdc_config.h | 1890 ++++++++++++++++++++ drivers/amlogic/media/gdc/inc/sys/system_gdc_io.h | 44 + drivers/amlogic/media/gdc/inc/sys/system_log.h | 55 + drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c | 280 +++ .../amlogic/media/gdc/src/platform/system_gdc_io.c | 66 + .../amlogic/media/gdc/src/platform/system_log.c | 21 + 16 files changed, 2959 insertions(+) create mode 100644 drivers/amlogic/media/gdc/Kconfig create mode 100644 drivers/amlogic/media/gdc/Makefile create mode 100644 drivers/amlogic/media/gdc/app/gdc_main.c create mode 100644 drivers/amlogic/media/gdc/app/gdc_module.c create mode 100644 drivers/amlogic/media/gdc/inc/api/gdc_api.h create mode 100644 drivers/amlogic/media/gdc/inc/gdc/gdc_config.h create mode 100644 drivers/amlogic/media/gdc/inc/sys/system_gdc_io.h create mode 100644 drivers/amlogic/media/gdc/inc/sys/system_log.h create mode 100644 drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c create mode 100644 drivers/amlogic/media/gdc/src/platform/system_gdc_io.c create mode 100644 drivers/amlogic/media/gdc/src/platform/system_log.c diff --git a/MAINTAINERS b/MAINTAINERS index 0c5d4e5..788cba4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14398,6 +14398,10 @@ AMLOGIC G12A Media codec io bus M: Nanxin Qin F: include/linux/amlogic/media/registers/regs/efuse_regs.h +AMLOGIC Geometric Distorition Correction +M: Jiyu Yang +F: drivers/amlogic/media/gdc/* + AMLOGIC G12A CVBS DRIVER M: Nian Jing F: drivers/amlogic/media/vout/cvbs/ diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 7e7bc3a..4496f1b 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -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"; diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 17f04bb..c0c0fe4 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -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 diff --git a/drivers/amlogic/media/Kconfig b/drivers/amlogic/media/Kconfig index 2cde7c3..bb5673d 100644 --- a/drivers/amlogic/media/Kconfig +++ b/drivers/amlogic/media/Kconfig @@ -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 diff --git a/drivers/amlogic/media/Makefile b/drivers/amlogic/media/Makefile index 9702f1b..8db1870 100644 --- a/drivers/amlogic/media/Makefile +++ b/drivers/amlogic/media/Makefile @@ -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/ diff --git a/drivers/amlogic/media/gdc/Kconfig b/drivers/amlogic/media/gdc/Kconfig new file mode 100644 index 0000000..b1a0d63 --- /dev/null +++ b/drivers/amlogic/media/gdc/Kconfig @@ -0,0 +1,8 @@ +# +# gdc driver configuration +# +config AMLOGIC_MEDIA_GDC + bool "Amlogic gdc driver" + default n + help + Select to enable gdc driver. diff --git a/drivers/amlogic/media/gdc/Makefile b/drivers/amlogic/media/gdc/Makefile new file mode 100644 index 0000000..5892420 --- /dev/null +++ b/drivers/amlogic/media/gdc/Makefile @@ -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 diff --git a/drivers/amlogic/media/gdc/app/gdc_main.c b/drivers/amlogic/media/gdc/app/gdc_main.c new file mode 100644 index 0000000..6b43d73 --- /dev/null +++ b/drivers/amlogic/media/gdc/app/gdc_main.c @@ -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 +#include +//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; +} diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c new file mode 100644 index 0000000..b0de1c6 --- /dev/null +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "system_log.h" + +#include +#include +#include +#include +//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"); diff --git a/drivers/amlogic/media/gdc/inc/api/gdc_api.h b/drivers/amlogic/media/gdc/inc/api/gdc_api.h new file mode 100644 index 0000000..2648666 --- /dev/null +++ b/drivers/amlogic/media/gdc/inc/api/gdc_api.h @@ -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 + +#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 diff --git a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h new file mode 100644 index 0000000..01fd6bc --- /dev/null +++ b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h @@ -0,0 +1,1890 @@ +/* + * drivers/amlogic/media/gdc/inc/gdc/gdc_config.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_CONFIG_H__ +#define __GDC_CONFIG_H__ + +#include +#include +#include +#include +#include "system_gdc_io.h" +#include "gdc_api.h" + +struct gdc_settings; +struct meson_gdc_dev_t { + struct platform_device *pdev; + void *reg_base; + struct clk *clk_core; + struct clk *clk_axi; + spinlock_t slock; + int irq; +}; + +struct mgdc_fh_s { + struct list_head list; + wait_queue_head_t irq_queue; + struct meson_gdc_dev_t *gdev; + char task_comm[32]; + struct ion_client *ion_client; + struct gdc_settings gs; +}; + +irqreturn_t interrupt_handler_next(int irq, void *param); +// ----------------------------------- // +// Instance 'gdc' of module 'gdc_ip_config' +// ----------------------------------- // + +#define GDC_BASE_ADDR (0x00L) +#define GDC_SIZE (0x100) + +// ----------------------------------- // +// Group: ID +// ----------------------------------- // + +// ----------------------------------- // +// Register: API +// ----------------------------------- // + +#define GDC_ID_API_DEFAULT (0x0) +#define GDC_ID_API_DATASIZE (32) +#define GDC_ID_API_OFFSET (0x0) +#define GDC_ID_API_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_id_api_read(void) +{ + return system_gdc_read_32(0x00L); +} +// ----------------------------------- // +// Register: Product +// ----------------------------------- // + +#define GDC_ID_PRODUCT_DEFAULT (0x0) +#define GDC_ID_PRODUCT_DATASIZE (32) +#define GDC_ID_PRODUCT_OFFSET (0x4) +#define GDC_ID_PRODUCT_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_id_product_read(void) +{ + return system_gdc_read_32(0x04L); +} +// ----------------------------------- // +// Register: Version +// ----------------------------------- // + +#define GDC_ID_VERSION_DEFAULT (0x0) +#define GDC_ID_VERSION_DATASIZE (32) +#define GDC_ID_VERSION_OFFSET (0x8) +#define GDC_ID_VERSION_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_id_version_read(void) +{ + return system_gdc_read_32(0x08L); +} +// ----------------------------------- // +// Register: Revision +// ----------------------------------- // + +#define GDC_ID_REVISION_DEFAULT (0x0) +#define GDC_ID_REVISION_DATASIZE (32) +#define GDC_ID_REVISION_OFFSET (0xc) +#define GDC_ID_REVISION_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_id_revision_read(void) +{ + return system_gdc_read_32(0x0cL); +} +// ----------------------------------- // +// Group: GDC +// ----------------------------------- // +// ----------------------------------- // +// GDC controls +// ----------------------------------- // +// ----------------------------------- // +// Register: config addr +// ----------------------------------- // +// ----------------------------------- // +// Base address of configuration stream +// (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_CONFIG_ADDR_DEFAULT (0x0) +#define GDC_CONFIG_ADDR_DATASIZE (32) +#define GDC_CONFIG_ADDR_OFFSET (0x10) +#define GDC_CONFIG_ADDR_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_config_addr_write(uint32_t data) +{ + system_gdc_write_32(0x10L, data); +} +static inline uint32_t gdc_config_addr_read(void) +{ + return system_gdc_read_32(0x10L); +} +// ----------------------------------- // +// Register: config size +// ----------------------------------- // +// ----------------------------------- // +// Size of the configuration stream // +// (in bytes, 32 bit word granularity) // +// ----------------------------------- // + +#define GDC_CONFIG_SIZE_DEFAULT (0x0) +#define GDC_CONFIG_SIZE_DATASIZE (32) +#define GDC_CONFIG_SIZE_OFFSET (0x14) +#define GDC_CONFIG_SIZE_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_config_size_write(uint32_t data) +{ + system_gdc_write_32(0x14L, data); +} +static inline uint32_t gdc_config_size_read(void) +{ + return system_gdc_read_32(0x14L); +} +// ----------------------------------- // +// Register: datain width +// ----------------------------------- // + +// ----------------------------------- // +// Width of the input image (in pixels) +// ----------------------------------- // + +#define GDC_DATAIN_WIDTH_DEFAULT (0x0) +#define GDC_DATAIN_WIDTH_DATASIZE (16) +#define GDC_DATAIN_WIDTH_OFFSET (0x20) +#define GDC_DATAIN_WIDTH_MASK (0xffff) + +// args: data (16-bit) +static inline void gdc_datain_width_write(uint16_t data) +{ + uint32_t curr = system_gdc_read_32(0x20L); + + system_gdc_write_32(0x20L, ((curr & 0xffff0000) | data)); +} +static inline uint16_t gdc_datain_width_read(void) +{ + return (uint16_t)((system_gdc_read_32(0x20L) & 0xffff) >> 0); +} +// ----------------------------------- // +// Register: datain_height +// ----------------------------------- // + +// ----------------------------------- // +// Height of the input image (in pixels) +// ----------------------------------- // + +#define GDC_DATAIN_HEIGHT_DEFAULT (0x0) +#define GDC_DATAIN_HEIGHT_DATASIZE (16) +#define GDC_DATAIN_HEIGHT_OFFSET (0x24) +#define GDC_DATAIN_HEIGHT_MASK (0xffff) + +// args: data (16-bit) +static inline void gdc_datain_height_write(uint16_t data) +{ + uint32_t curr = system_gdc_read_32(0x24L); + + system_gdc_write_32(0x24L, ((curr & 0xffff0000) | data)); +} +static inline uint16_t gdc_datain_height_read(void) +{ + return (uint16_t)((system_gdc_read_32(0x24L) & 0xffff) >> 0); +} +// ----------------------------------- // +// Register: data1in addr +// ----------------------------------- // + +// ----------------------------------- // +// Base address of the 1st plane in the +// input frame buffer +// (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA1IN_ADDR_DEFAULT (0x0) +#define GDC_DATA1IN_ADDR_DATASIZE (32) +#define GDC_DATA1IN_ADDR_OFFSET (0x28) +#define GDC_DATA1IN_ADDR_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data1in_addr_write(uint32_t data) +{ + system_gdc_write_32(0x28L, data); +} +static inline uint32_t gdc_data1in_addr_read(void) +{ + return system_gdc_read_32(0x28L); +} +// ----------------------------------- // +// Register: data1in line offset +// ----------------------------------- // + +// ----------------------------------- // +// Address difference between adjacent +// lines for the 1st plane in the input +// frame buffer (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA1IN_LINE_OFFSET_DEFAULT (0x0) +#define GDC_DATA1IN_LINE_OFFSET_DATASIZE (32) +#define GDC_DATA1IN_LINE_OFFSET_OFFSET (0x2c) +#define GDC_DATA1IN_LINE_OFFSET_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data1in_line_offset_write(uint32_t data) +{ + system_gdc_write_32(0x2cL, data); +} +static inline uint32_t gdc_data1in_line_offset_read(void) +{ + return system_gdc_read_32(0x2cL); +} +// ----------------------------------- // +// Register: data2in addr +// ----------------------------------- // + +// ----------------------------------- // +// Address of the 2nd plane in the +// input frame buffer +// (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA2IN_ADDR_DEFAULT (0x0) +#define GDC_DATA2IN_ADDR_DATASIZE (32) +#define GDC_DATA2IN_ADDR_OFFSET (0x30) +#define GDC_DATA2IN_ADDR_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data2in_addr_write(uint32_t data) +{ + system_gdc_write_32(0x30L, data); +} +static inline uint32_t gdc_data2in_addr_read(void) +{ + return system_gdc_read_32(0x30L); +} +// ----------------------------------- // +// Register: data2in line offset +// ----------------------------------- // + +// ----------------------------------- // +// Address difference between adjacent +// lines for the 2nd plane in the input +// frame buffer (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA2IN_LINE_OFFSET_DEFAULT (0x0) +#define GDC_DATA2IN_LINE_OFFSET_DATASIZE (32) +#define GDC_DATA2IN_LINE_OFFSET_OFFSET (0x34) +#define GDC_DATA2IN_LINE_OFFSET_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data2in_line_offset_write(uint32_t data) +{ + system_gdc_write_32(0x34L, data); +} +static inline uint32_t gdc_data2in_line_offset_read(void) +{ + return system_gdc_read_32(0x34L); +} +// ----------------------------------- // +// Register: data3in addr +// ----------------------------------- // + +// ----------------------------------- // +// Base address of the 3rd plane in the +// input frame buffer +// (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA3IN_ADDR_DEFAULT (0x0) +#define GDC_DATA3IN_ADDR_DATASIZE (32) +#define GDC_DATA3IN_ADDR_OFFSET (0x38) +#define GDC_DATA3IN_ADDR_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data3in_addr_write(uint32_t data) +{ + system_gdc_write_32(0x38L, data); +} +static inline uint32_t gdc_data3in_addr_read(void) +{ + return system_gdc_read_32(0x38L); +} +// ----------------------------------- // +// Register: data3in line offset +// ----------------------------------- // + +// ----------------------------------- // +// Address difference between adjacent +// lines for the 3rd plane in the +// input frame buffer (in bytes, +// AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA3IN_LINE_OFFSET_DEFAULT (0x0) +#define GDC_DATA3IN_LINE_OFFSET_DATASIZE (32) +#define GDC_DATA3IN_LINE_OFFSET_OFFSET (0x3c) +#define GDC_DATA3IN_LINE_OFFSET_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data3in_line_offset_write(uint32_t data) +{ + system_gdc_write_32(0x3cL, data); +} +static inline uint32_t gdc_data3in_line_offset_read(void) +{ + return system_gdc_read_32(0x3cL); +} +// ----------------------------------- // +// Register: dataout width +// ----------------------------------- // + +// ----------------------------------- // +// Width of the output image (in pixels) +// ----------------------------------- // + +#define GDC_DATAOUT_WIDTH_DEFAULT (0x0) +#define GDC_DATAOUT_WIDTH_DATASIZE (16) +#define GDC_DATAOUT_WIDTH_OFFSET (0x40) +#define GDC_DATAOUT_WIDTH_MASK (0xffff) + +// args: data (16-bit) +static inline void gdc_dataout_width_write(uint16_t data) +{ + uint32_t curr = system_gdc_read_32(0x40L); + + system_gdc_write_32(0x40L, ((curr & 0xffff0000) | data)); +} +static inline uint16_t gdc_dataout_width_read(void) +{ + return (uint16_t)((system_gdc_read_32(0x40L) & 0xffff) >> 0); +} +// ----------------------------------- // +// Register: dataout height +// ----------------------------------- // + +// ----------------------------------- // +// Height of the output image (in pixels) +// ----------------------------------- // + +#define GDC_DATAOUT_HEIGHT_DEFAULT (0x0) +#define GDC_DATAOUT_HEIGHT_DATASIZE (16) +#define GDC_DATAOUT_HEIGHT_OFFSET (0x44) +#define GDC_DATAOUT_HEIGHT_MASK (0xffff) + +// args: data (16-bit) +static inline void gdc_dataout_height_write(uint16_t data) +{ + uint32_t curr = system_gdc_read_32(0x44L); + + system_gdc_write_32(0x44L, ((curr & 0xffff0000) | data)); +} +static inline uint16_t gdc_dataout_height_read(void) +{ + return (uint16_t)((system_gdc_read_32(0x44L) & 0xffff) >> 0); +} +// ----------------------------------- // +// Register: data1out addr +// ----------------------------------- // + +// ----------------------------------- // +// Base address of the 1st plane in the +// output frame buffer +// (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA1OUT_ADDR_DEFAULT (0x0) +#define GDC_DATA1OUT_ADDR_DATASIZE (32) +#define GDC_DATA1OUT_ADDR_OFFSET (0x48) +#define GDC_DATA1OUT_ADDR_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data1out_addr_write(uint32_t data) +{ + system_gdc_write_32(0x48L, data); +} +static inline uint32_t gdc_data1out_addr_read(void) +{ + return system_gdc_read_32(0x48L); +} +// ----------------------------------- // +// Register: data1out line offset +// ----------------------------------- // + +// ----------------------------------- // +// Address difference between adjacent +// lines for the 1st plane in the +// output frame buffer (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA1OUT_LINE_OFFSET_DEFAULT (0x0) +#define GDC_DATA1OUT_LINE_OFFSET_DATASIZE (32) +#define GDC_DATA1OUT_LINE_OFFSET_OFFSET (0x4c) +#define GDC_DATA1OUT_LINE_OFFSET_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data1out_line_offset_write(uint32_t data) +{ + system_gdc_write_32(0x4cL, data); +} +static inline uint32_t gdc_data1out_line_offset_read(void) +{ + return system_gdc_read_32(0x4cL); +} +// ----------------------------------- // +// Register: data2out addr +// ----------------------------------- // + +// ----------------------------------- // +// Base address of the 2nd plane in the +// output frame buffer (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA2OUT_ADDR_DEFAULT (0x0) +#define GDC_DATA2OUT_ADDR_DATASIZE (32) +#define GDC_DATA2OUT_ADDR_OFFSET (0x50) +#define GDC_DATA2OUT_ADDR_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data2out_addr_write(uint32_t data) +{ + system_gdc_write_32(0x50L, data); +} +static inline uint32_t gdc_data2out_addr_read(void) +{ + return system_gdc_read_32(0x50L); +} +// ----------------------------------- // +// Register: data2out line offset +// ----------------------------------- // + +// ----------------------------------- // +// Address difference between adjacent lines +// for the 2ndt plane in the +// output frame buffer (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA2OUT_LINE_OFFSET_DEFAULT (0x0) +#define GDC_DATA2OUT_LINE_OFFSET_DATASIZE (32) +#define GDC_DATA2OUT_LINE_OFFSET_OFFSET (0x54) +#define GDC_DATA2OUT_LINE_OFFSET_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data2out_line_offset_write(uint32_t data) +{ + system_gdc_write_32(0x54L, data); +} +static inline uint32_t gdc_data2out_line_offset_read(void) +{ + return system_gdc_read_32(0x54L); +} +// ----------------------------------- // +// Register: data3out addr +// ----------------------------------- // + +// ----------------------------------- // +// Base address of the 3rd plane in the +// output frame buffer (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA3OUT_ADDR_DEFAULT (0x0) +#define GDC_DATA3OUT_ADDR_DATASIZE (32) +#define GDC_DATA3OUT_ADDR_OFFSET (0x58) +#define GDC_DATA3OUT_ADDR_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data3out_addr_write(uint32_t data) +{ + system_gdc_write_32(0x58L, data); +} +static inline uint32_t gdc_data3out_addr_read(void) +{ + return system_gdc_read_32(0x58L); +} +// ----------------------------------- // +// Register: data3out line offset +// ----------------------------------- // + +// ----------------------------------- // +// Address difference between adjacent +// lines for the 3rd plane in the +// output frame buffer (in bytes, AXI word aligned) +// ----------------------------------- // + +#define GDC_DATA3OUT_LINE_OFFSET_DEFAULT (0x0) +#define GDC_DATA3OUT_LINE_OFFSET_DATASIZE (32) +#define GDC_DATA3OUT_LINE_OFFSET_OFFSET (0x5c) +#define GDC_DATA3OUT_LINE_OFFSET_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_data3out_line_offset_write(uint32_t data) +{ + system_gdc_write_32(0x5cL, data); +} +static inline uint32_t gdc_data3out_line_offset_read(void) +{ + return system_gdc_read_32(0x5cL); +} +// ----------------------------------- // +// Register: status +// ----------------------------------- // + +// ----------------------------------- // +// word with status fields: +// ----------------------------------- // + +#define GDC_STATUS_DEFAULT (0x0) +#define GDC_STATUS_DATASIZE (32) +#define GDC_STATUS_OFFSET (0x60) +#define GDC_STATUS_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_status_read(void) +{ + return system_gdc_read_32(0x60L); +} +// ----------------------------------- // +// Register: busy +// ----------------------------------- // + +// ----------------------------------- // +// Busy 1 = processing in progress, +// 0 = ready for next image +// ----------------------------------- // + +#define GDC_BUSY_DEFAULT (0x0) +#define GDC_BUSY_DATASIZE (1) +#define GDC_BUSY_OFFSET (0x60) +#define GDC_BUSY_MASK (0x1) + +// args: data (1-bit) +static inline void gdc_busy_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x60L); + + system_gdc_write_32(0x60L, ((data & 0x1) << 0) | (curr & 0xfffffffe)); +} +static inline uint8_t gdc_busy_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x60L) & 0x1) >> 0); +} +// ----------------------------------- // +// Register: error +// ----------------------------------- // + +// ----------------------------------- // +// Error flag: last operation was finished with error (see bits 15:8) +// ----------------------------------- // + +#define GDC_ERROR_DEFAULT (0x0) +#define GDC_ERROR_DATASIZE (1) +#define GDC_ERROR_OFFSET (0x60) +#define GDC_ERROR_MASK (0x2) + +// args: data (1-bit) +static inline void gdc_error_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x60L); + uint32_t val = ((data & 0x1) << 1) | (curr & 0xfffffffd); + + system_gdc_write_32(0x60L, val); +} +static inline uint8_t gdc_error_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x60L) & 0x2) >> 1); +} +// ----------------------------------- // +// Register: Reserved for future use 1 +// ----------------------------------- // + +#define GDC_RESERVED_FOR_FUTURE_USE_1_DEFAULT (0x0) +#define GDC_RESERVED_FOR_FUTURE_USE_1_DATASIZE (6) +#define GDC_RESERVED_FOR_FUTURE_USE_1_OFFSET (0x60) +#define GDC_RESERVED_FOR_FUTURE_USE_1_MASK (0xfc) + +// args: data (6-bit) +static inline void gdc_reserved_for_future_use_1_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x60L); + uint32_t val = ((data & 0x3f) << 2) | (curr & 0xffffff03); + + system_gdc_write_32(0x60L, val); +} +static inline uint8_t gdc_reserved_for_future_use_1_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x60L) & 0xfc) >> 2); +} +// ----------------------------------- // +// Register: configuration error +// ----------------------------------- // + +// ----------------------------------- // +// Configuration error (wrong configuration stream) +// ----------------------------------- // + +#define GDC_CONFIGURATION_ERROR_DEFAULT (0x0) +#define GDC_CONFIGURATION_ERROR_DATASIZE (1) +#define GDC_CONFIGURATION_ERROR_OFFSET (0x60) +#define GDC_CONFIGURATION_ERROR_MASK (0x100) + +// args: data (1-bit) +static inline void gdc_configuration_error_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x60L); + uint32_t val = ((data & 0x1) << 8) | (curr & 0xfffffeff); + + system_gdc_write_32(0x60L, val); +} +static inline uint8_t gdc_configuration_error_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x60L) & 0x100) >> 8); +} +// ----------------------------------- // +// Register: user abort +// ----------------------------------- // + +// ----------------------------------- // +// User abort (stop/reset command) +// ----------------------------------- // + +#define GDC_USER_ABORT_DEFAULT (0x0) +#define GDC_USER_ABORT_DATASIZE (1) +#define GDC_USER_ABORT_OFFSET (0x60) +#define GDC_USER_ABORT_MASK (0x200) + +// args: data (1-bit) +static inline void gdc_user_abort_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x60L); + uint32_t val = ((data & 0x1) << 9) | (curr & 0xfffffdff); + + system_gdc_write_32(0x60L, val); +} +static inline uint8_t gdc_user_abort_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x60L) & 0x200) >> 9); +} +// ----------------------------------- // +// Register: AXI reader error +// ----------------------------------- // + +// ----------------------------------- // +// AXI reader error (e.g. error code returned by fabric) +// ----------------------------------- // + +#define GDC_AXI_READER_ERROR_DEFAULT (0x0) +#define GDC_AXI_READER_ERROR_DATASIZE (1) +#define GDC_AXI_READER_ERROR_OFFSET (0x60) +#define GDC_AXI_READER_ERROR_MASK (0x400) + +// args: data (1-bit) +static inline void gdc_axi_reader_error_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x60L); + uint32_t val = ((data & 0x1) << 10) | (curr & 0xfffffbff); + + system_gdc_write_32(0x60L, val); +} +static inline uint8_t gdc_axi_reader_error_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x60L) & 0x400) >> 10); +} +// ----------------------------------- // +// Register: AXI writer error +// ----------------------------------- // + +// ----------------------------------- // +// AXI writer error +// ----------------------------------- // + +#define GDC_AXI_WRITER_ERROR_DEFAULT (0x0) +#define GDC_AXI_WRITER_ERROR_DATASIZE (1) +#define GDC_AXI_WRITER_ERROR_OFFSET (0x60) +#define GDC_AXI_WRITER_ERROR_MASK (0x800) + +// args: data (1-bit) +static inline void gdc_axi_writer_error_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x60L); + uint32_t val = ((data & 0x1) << 11) | (curr & 0xfffff7ff); + + system_gdc_write_32(0x60L, val); +} +static inline uint8_t gdc_axi_writer_error_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x60L) & 0x800) >> 11); +} +// ----------------------------------- // +// Register: Unaligned access +// ----------------------------------- // + +// ----------------------------------- // +// Unaligned access (address pointer is not aligned) +// ----------------------------------- // + +#define GDC_UNALIGNED_ACCESS_DEFAULT (0x0) +#define GDC_UNALIGNED_ACCESS_DATASIZE (1) +#define GDC_UNALIGNED_ACCESS_OFFSET (0x60) +#define GDC_UNALIGNED_ACCESS_MASK (0x1000) + +// args: data (1-bit) +static inline void gdc_unaligned_access_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x60L); + uint32_t val = ((data & 0x1) << 12) | (curr & 0xffffefff); + + system_gdc_write_32(0x60L, val); +} +static inline uint8_t gdc_unaligned_access_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x60L) & 0x1000) >> 12); +} +// ----------------------------------- // +// Register: Incompatible configuration +// ----------------------------------- // + +// ----------------------------------- // +// Incompatible configuration (request +// of unimplemented mode of operation, +// e.g. unsupported image format, +// unsupported module mode in the configuration stream) +// ----------------------------------- // + +#define GDC_INCOMPATIBLE_CONFIGURATION_DEFAULT (0x0) +#define GDC_INCOMPATIBLE_CONFIGURATION_DATASIZE (1) +#define GDC_INCOMPATIBLE_CONFIGURATION_OFFSET (0x60) +#define GDC_INCOMPATIBLE_CONFIGURATION_MASK (0x2000) + +// args: data (1-bit) +static inline void gdc_incompatible_configuration_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x60L); + uint32_t val = ((data & 0x1) << 13) | (curr & 0xffffdfff); + + system_gdc_write_32(0x60L, val); +} +static inline uint8_t gdc_incompatible_configuration_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x60L) & 0x2000) >> 13); +} +// ----------------------------------- // +// Register: Reserved for future use 2 +// ----------------------------------- // + +#define GDC_RESERVED_FOR_FUTURE_USE_2_DEFAULT (0x0) +#define GDC_RESERVED_FOR_FUTURE_USE_2_DATASIZE (18) +#define GDC_RESERVED_FOR_FUTURE_USE_2_OFFSET (0x60) +#define GDC_RESERVED_FOR_FUTURE_USE_2_MASK (0xffffc000) + +// args: data (18-bit) +static inline void gdc_reserved_for_future_use_2_write(uint32_t data) +{ + uint32_t curr = system_gdc_read_32(0x60L); + uint32_t val = ((data & 0x3ffff) << 14) | (curr & 0x3fff); + + system_gdc_write_32(0x60L, val); +} +static inline uint32_t gdc_reserved_for_future_use_2_read(void) +{ + return (uint32_t)((system_gdc_read_32(0x60L) & 0xffffc000) >> 14); +} +// ----------------------------------- // +// Register: config +// ----------------------------------- // + +#define GDC_CONFIG_DEFAULT (0x0) +#define GDC_CONFIG_DATASIZE (32) +#define GDC_CONFIG_OFFSET (0x64) +#define GDC_CONFIG_MASK (0xffffffff) + +// args: data (32-bit) +static inline void gdc_config_write(uint32_t data) +{ + system_gdc_write_32(0x64L, data); +} +static inline uint32_t gdc_config_read(void) +{ + return system_gdc_read_32(0x64L); +} +// ----------------------------------- // +// Register: start flag +// ----------------------------------- // + +// ----------------------------------- // +// Start flag: transition from 0 to 1 +// latches the data on the configuration ports +// and starts the processing +// ----------------------------------- // + +#define GDC_START_FLAG_DEFAULT (0x0) +#define GDC_START_FLAG_DATASIZE (1) +#define GDC_START_FLAG_OFFSET (0x64) +#define GDC_START_FLAG_MASK (0x1) + +// args: data (1-bit) +static inline void gdc_start_flag_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x64L); + uint32_t val = ((data & 0x1) << 0) | (curr & 0xfffffffe); + + system_gdc_write_32(0x64L, val); +} +static inline uint8_t gdc_start_flag_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x64L) & 0x1) >> 0); +} +// ----------------------------------- // +// Register: stop flag +// ----------------------------------- // + +// ----------------------------------- // +// Stop/reset flag: 0 - normal operation, +// 1 means to initiate internal cleanup procedure +// to abandon the current frame +// and prepare for processing of the next frame. +// The busy flag in status word should be +// cleared at the end of this process +// ----------------------------------- // + +#define GDC_STOP_FLAG_DEFAULT (0x0) +#define GDC_STOP_FLAG_DATASIZE (1) +#define GDC_STOP_FLAG_OFFSET (0x64) +#define GDC_STOP_FLAG_MASK (0x2) + +// args: data (1-bit) +static inline void gdc_stop_flag_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x64L); + uint32_t val = ((data & 0x1) << 1) | (curr & 0xfffffffd); + + system_gdc_write_32(0x64L, val); +} +static inline uint8_t gdc_stop_flag_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x64L) & 0x2) >> 1); +} +// ----------------------------------- // +// Register: Reserved for future use 3 +// ----------------------------------- // + +#define GDC_RESERVED_FOR_FUTURE_USE_3_DEFAULT (0x0) +#define GDC_RESERVED_FOR_FUTURE_USE_3_DATASIZE (30) +#define GDC_RESERVED_FOR_FUTURE_USE_3_OFFSET (0x64) +#define GDC_RESERVED_FOR_FUTURE_USE_3_MASK (0xfffffffc) + +// args: data (30-bit) +static inline void gdc_reserved_for_future_use_3_write(uint32_t data) +{ + uint32_t curr = system_gdc_read_32(0x64L); + uint32_t val = ((data & 0x3fffffff) << 2) | (curr & 0x3); + + system_gdc_write_32(0x64L, val); +} +static inline uint32_t gdc_reserved_for_future_use_3_read(void) +{ + return (uint32_t)((system_gdc_read_32(0x64L) & 0xfffffffc) >> 2); +} +// ----------------------------------- // +// Register: Capability mask +// ----------------------------------- // + +#define GDC_CAPABILITY_MASK_DEFAULT (0x0) +#define GDC_CAPABILITY_MASK_DATASIZE (32) +#define GDC_CAPABILITY_MASK_OFFSET (0x68) +#define GDC_CAPABILITY_MASK_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_capability_mask_read(void) +{ + return system_gdc_read_32(0x68L); +} +// ----------------------------------- // +// Register: Eight bit data suppoirted +// ----------------------------------- // + +// ----------------------------------- // +// 8 bit data supported +// ----------------------------------- // + +#define GDC_EIGHT_BIT_DATA_SUPPOIRTED_DEFAULT (0x0) +#define GDC_EIGHT_BIT_DATA_SUPPOIRTED_DATASIZE (1) +#define GDC_EIGHT_BIT_DATA_SUPPOIRTED_OFFSET (0x68) +#define GDC_EIGHT_BIT_DATA_SUPPOIRTED_MASK (0x1) + +// args: data (1-bit) +static inline void gdc_eight_bit_data_suppoirted_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 0) | (curr & 0xfffffffe); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_eight_bit_data_suppoirted_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x1) >> 0); +} +// ----------------------------------- // +// Register: Ten bit data supported +// ----------------------------------- // + +// ----------------------------------- // +// 10 bit data supported +// ----------------------------------- // + +#define GDC_TEN_BIT_DATA_SUPPORTED_DEFAULT (0x0) +#define GDC_TEN_BIT_DATA_SUPPORTED_DATASIZE (1) +#define GDC_TEN_BIT_DATA_SUPPORTED_OFFSET (0x68) +#define GDC_TEN_BIT_DATA_SUPPORTED_MASK (0x2) + +// args: data (1-bit) +static inline void gdc_ten_bit_data_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 1) | (curr & 0xfffffffd); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_ten_bit_data_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x2) >> 1); +} +// ----------------------------------- // +// Register: Grayscale supported +// ----------------------------------- // + +// ----------------------------------- // +// grayscale supported +// ----------------------------------- // + +#define GDC_GRAYSCALE_SUPPORTED_DEFAULT (0x0) +#define GDC_GRAYSCALE_SUPPORTED_DATASIZE (1) +#define GDC_GRAYSCALE_SUPPORTED_OFFSET (0x68) +#define GDC_GRAYSCALE_SUPPORTED_MASK (0x4) + +// args: data (1-bit) +static inline void gdc_grayscale_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 2) | (curr & 0xfffffffb); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_grayscale_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x4) >> 2); +} +// ----------------------------------- // +// Register: RGBA888 supported +// ----------------------------------- // + +// ----------------------------------- // +// RGBA8:8:8/YUV4:4:4 mode supported +// ----------------------------------- // + +#define GDC_RGBA888_SUPPORTED_DEFAULT (0x0) +#define GDC_RGBA888_SUPPORTED_DATASIZE (1) +#define GDC_RGBA888_SUPPORTED_OFFSET (0x68) +#define GDC_RGBA888_SUPPORTED_MASK (0x8) + +// args: data (1-bit) +static inline void gdc_rgba888_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 3) | (curr & 0xfffffff7); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_rgba888_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x8) >> 3); +} +// ----------------------------------- // +// Register: RGB YUV444 planar supported +// ----------------------------------- // + +// ----------------------------------- // +// RGB/YUV444 planar modes supported +// ----------------------------------- // + +#define GDC_RGB_YUV444_PLANAR_SUPPORTED_DEFAULT (0x0) +#define GDC_RGB_YUV444_PLANAR_SUPPORTED_DATASIZE (1) +#define GDC_RGB_YUV444_PLANAR_SUPPORTED_OFFSET (0x68) +#define GDC_RGB_YUV444_PLANAR_SUPPORTED_MASK (0x10) + +// args: data (1-bit) +static inline void gdc_rgb_yuv444_planar_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 4) | (curr & 0xffffffef); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_rgb_yuv444_planar_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x10) >> 4); +} +// ----------------------------------- // +// Register: YUV semiplanar supported +// ----------------------------------- // + +// ----------------------------------- // +// YUV semiplanar modes supported +// ----------------------------------- // + +#define GDC_YUV_SEMIPLANAR_SUPPORTED_DEFAULT (0x0) +#define GDC_YUV_SEMIPLANAR_SUPPORTED_DATASIZE (1) +#define GDC_YUV_SEMIPLANAR_SUPPORTED_OFFSET (0x68) +#define GDC_YUV_SEMIPLANAR_SUPPORTED_MASK (0x20) + +// args: data (1-bit) +static inline void gdc_yuv_semiplanar_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 5) | (curr & 0xffffffdf); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_yuv_semiplanar_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x20) >> 5); +} +// ----------------------------------- // +// Register: YUV422 linear mode supported +// ----------------------------------- // + +// ----------------------------------- // +// YUV4:2:2 linear mode supported (16 bit/pixel) +// ----------------------------------- // + +#define GDC_YUV422_LINEAR_MODE_SUPPORTED_DEFAULT (0x0) +#define GDC_YUV422_LINEAR_MODE_SUPPORTED_DATASIZE (1) +#define GDC_YUV422_LINEAR_MODE_SUPPORTED_OFFSET (0x68) +#define GDC_YUV422_LINEAR_MODE_SUPPORTED_MASK (0x40) + +// args: data (1-bit) +static inline void gdc_yuv422_linear_mode_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 6) | (curr & 0xffffffbf); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_yuv422_linear_mode_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x40) >> 6); +} +// ----------------------------------- // +// Register: RGB10_10_10 supported +// ----------------------------------- // + +// ----------------------------------- // +// RGB10:10:10 mode supported +// ----------------------------------- // + +#define GDC_RGB10_10_10_SUPPORTED_DEFAULT (0x0) +#define GDC_RGB10_10_10_SUPPORTED_DATASIZE (1) +#define GDC_RGB10_10_10_SUPPORTED_OFFSET (0x68) +#define GDC_RGB10_10_10_SUPPORTED_MASK (0x80) + +// args: data (1-bit) +static inline void gdc_rgb10_10_10_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 7) | (curr & 0xffffff7f); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_rgb10_10_10_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x80) >> 7); +} +// ----------------------------------- // +// Register: Bicubic interpolation supported +// ----------------------------------- // + +// ----------------------------------- // +// 4 tap bicubic interpolation supported +// ----------------------------------- // + +#define GDC_BICUBIC_INTERPOLATION_SUPPORTED_DEFAULT (0x0) +#define GDC_BICUBIC_INTERPOLATION_SUPPORTED_DATASIZE (1) +#define GDC_BICUBIC_INTERPOLATION_SUPPORTED_OFFSET (0x68) +#define GDC_BICUBIC_INTERPOLATION_SUPPORTED_MASK (0x100) + +// args: data (1-bit) +static inline void gdc_bicubic_interpolation_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 8) | (curr & 0xfffffeff); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_bicubic_interpolation_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x100) >> 8); +} +// ----------------------------------- // +// Register: Bilinear interpolation mode 1 supported +// ----------------------------------- // + +// ----------------------------------- // +// bilinear interpolation mode 1 supported {for U,V components} +// ----------------------------------- // + +#define GDC_BILINEAR_INTERPOLATION_MODE_1_SUPPORTED_DEFAULT (0x0) +#define GDC_BILINEAR_INTERPOLATION_MODE_1_SUPPORTED_DATASIZE (1) +#define GDC_BILINEAR_INTERPOLATION_MODE_1_SUPPORTED_OFFSET (0x68) +#define GDC_BILINEAR_INTERPOLATION_MODE_1_SUPPORTED_MASK (0x200) + +// args: data (1-bit) +static inline void +gdc_bilinear_interpolation_mode_1_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 9) | (curr & 0xfffffdff); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_bilinear_interpolation_mode_1_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x200) >> 9); +} +// ----------------------------------- // +// Register: Bilinear interpolation mode 2 supported +// ----------------------------------- // + +// ----------------------------------- // +// bilinear interpolation mode 2 supported {for U,V components} +// ----------------------------------- // + +#define GDC_BILINEAR_INTERPOLATION_MODE_2_SUPPORTED_DEFAULT (0x0) +#define GDC_BILINEAR_INTERPOLATION_MODE_2_SUPPORTED_DATASIZE (1) +#define GDC_BILINEAR_INTERPOLATION_MODE_2_SUPPORTED_OFFSET (0x68) +#define GDC_BILINEAR_INTERPOLATION_MODE_2_SUPPORTED_MASK (0x400) + +// args: data (1-bit) +static inline void +gdc_bilinear_interpolation_mode_2_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 10) | (curr & 0xfffffbff); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_bilinear_interpolation_mode_2_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x400) >> 10); +} +// ----------------------------------- // +// Register: Output of interpolation coordinates supported +// ----------------------------------- // + +// ----------------------------------- // +// output of interpolation coordinates is supported +// ----------------------------------- // + +#define GDC_OUTPUT_OF_INTERPOLATION_COORDINATES_SUPPORTED_DEFAULT (0x0) +#define GDC_OUTPUT_OF_INTERPOLATION_COORDINATES_SUPPORTED_DATASIZE (1) +#define GDC_OUTPUT_OF_INTERPOLATION_COORDINATES_SUPPORTED_OFFSET (0x68) +#define GDC_OUTPUT_OF_INTERPOLATION_COORDINATES_SUPPORTED_MASK (0x800) + +// args: data (1-bit) +static inline void +gdc_output_of_interpolation_coordinates_supported_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1) << 11) | (curr & 0xfffff7ff); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t +gdc_output_of_interpolation_coordinates_supported_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x800) >> 11); +} +// ----------------------------------- // +// Register: Reserved for future use 4 +// ----------------------------------- // + +#define GDC_RESERVED_FOR_FUTURE_USE_4_DEFAULT (0x0) +#define GDC_RESERVED_FOR_FUTURE_USE_4_DATASIZE (4) +#define GDC_RESERVED_FOR_FUTURE_USE_4_OFFSET (0x68) +#define GDC_RESERVED_FOR_FUTURE_USE_4_MASK (0xf000) + +// args: data (4-bit) +static inline void gdc_reserved_for_future_use_4_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0xf) << 12) | (curr & 0xffff0fff); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_reserved_for_future_use_4_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0xf000) >> 12); +} +// ----------------------------------- // +// Register: Size of output cache +// ----------------------------------- // + +// ----------------------------------- // +// log2(size of output cache in lines)-5 (0 - 32lines, 1 - 64 lines etc) +// ----------------------------------- // + +#define GDC_SIZE_OF_OUTPUT_CACHE_DEFAULT (0x0) +#define GDC_SIZE_OF_OUTPUT_CACHE_DATASIZE (3) +#define GDC_SIZE_OF_OUTPUT_CACHE_OFFSET (0x68) +#define GDC_SIZE_OF_OUTPUT_CACHE_MASK (0x70000) + +// args: data (3-bit) +static inline void gdc_size_of_output_cache_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x7) << 16) | (curr & 0xfff8ffff); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_size_of_output_cache_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x70000) >> 16); +} +// ----------------------------------- // +// Register: Size of tile cache +// ----------------------------------- // + +// ----------------------------------- // +// log2(size of tile cache in 16x16 clusters) +// ----------------------------------- // + +#define GDC_SIZE_OF_TILE_CACHE_DEFAULT (0x0) +#define GDC_SIZE_OF_TILE_CACHE_DATASIZE (5) +#define GDC_SIZE_OF_TILE_CACHE_OFFSET (0x68) +#define GDC_SIZE_OF_TILE_CACHE_MASK (0xf80000) + +// args: data (5-bit) +static inline void gdc_size_of_tile_cache_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x1f) << 19) | (curr & 0xff07ffff); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_size_of_tile_cache_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0xf80000) >> 19); +} +// ----------------------------------- // +// Register: Nuimber of polyphase filter banks +// ----------------------------------- // + +// ----------------------------------- // +// log2(number of polyphase filter banks) +// ----------------------------------- // + +#define GDC_NUIMBER_OF_POLYPHASE_FILTER_BANKS_DEFAULT (0x0) +#define GDC_NUIMBER_OF_POLYPHASE_FILTER_BANKS_DATASIZE (3) +#define GDC_NUIMBER_OF_POLYPHASE_FILTER_BANKS_OFFSET (0x68) +#define GDC_NUIMBER_OF_POLYPHASE_FILTER_BANKS_MASK (0x7000000) + +// args: data (3-bit) +static inline void gdc_nuimber_of_polyphase_filter_banks_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x7) << 24) | (curr & 0xf8ffffff); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_nuimber_of_polyphase_filter_banks_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x7000000) >> 24); +} +// ----------------------------------- // +// Register: AXI data width +// ----------------------------------- // + +// ----------------------------------- // +// log2(AXI_DATA_WIDTH)-5 +// ----------------------------------- // + +#define GDC_AXI_DATA_WIDTH_DEFAULT (0x0) +#define GDC_AXI_DATA_WIDTH_DATASIZE (3) +#define GDC_AXI_DATA_WIDTH_OFFSET (0x68) +#define GDC_AXI_DATA_WIDTH_MASK (0x38000000) + +// args: data (3-bit) +static inline void gdc_axi_data_width_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x7) << 27) | (curr & 0xc7ffffff); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_axi_data_width_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0x38000000) >> 27); +} +// ----------------------------------- // +// Register: Reserved for future use 5 +// ----------------------------------- // + +#define GDC_RESERVED_FOR_FUTURE_USE_5_DEFAULT (0x0) +#define GDC_RESERVED_FOR_FUTURE_USE_5_DATASIZE (2) +#define GDC_RESERVED_FOR_FUTURE_USE_5_OFFSET (0x68) +#define GDC_RESERVED_FOR_FUTURE_USE_5_MASK (0xc0000000) + +// args: data (2-bit) +static inline void gdc_reserved_for_future_use_5_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0x68L); + uint32_t val = ((data & 0x3) << 30) | (curr & 0x3fffffff); + + system_gdc_write_32(0x68L, val); +} +static inline uint8_t gdc_reserved_for_future_use_5_read(void) +{ + return (uint8_t)((system_gdc_read_32(0x68L) & 0xc0000000) >> 30); +} +// ----------------------------------- // +// Register: default ch1 +// ----------------------------------- // + +// ----------------------------------- // +// Default value for 1st data channel (Y/R color) +// to fill missing pixels (when coordinated +// are out of bound). LSB aligned +// ----------------------------------- // + +#define GDC_DEFAULT_CH1_DEFAULT (0x0) +#define GDC_DEFAULT_CH1_DATASIZE (12) +#define GDC_DEFAULT_CH1_OFFSET (0x70) +#define GDC_DEFAULT_CH1_MASK (0xfff) + +// args: data (12-bit) +static inline void gdc_default_ch1_write(uint16_t data) +{ + uint32_t curr = system_gdc_read_32(0x70L); + uint32_t val = ((data & 0xfff) << 0) | (curr & 0xfffff000); + + system_gdc_write_32(0x70L, val); +} +static inline uint16_t gdc_default_ch1_read(void) +{ + return (uint16_t)((system_gdc_read_32(0x70L) & 0xfff) >> 0); +} +// ----------------------------------- // +// Register: default ch2 +// ----------------------------------- // + +// ----------------------------------- // +// Default value for 2nd data channel +// (U/G color) to fill missing pixels +// (when coordinated are out of bound) LSB aligned +// ----------------------------------- // + +#define GDC_DEFAULT_CH2_DEFAULT (0x0) +#define GDC_DEFAULT_CH2_DATASIZE (12) +#define GDC_DEFAULT_CH2_OFFSET (0x74) +#define GDC_DEFAULT_CH2_MASK (0xfff) + +// args: data (12-bit) +static inline void gdc_default_ch2_write(uint16_t data) +{ + uint32_t curr = system_gdc_read_32(0x74L); + uint32_t val = ((data & 0xfff) << 0) | (curr & 0xfffff000); + + system_gdc_write_32(0x74L, val); +} +static inline uint16_t gdc_default_ch2_read(void) +{ + return (uint16_t)((system_gdc_read_32(0x74L) & 0xfff) >> 0); +} +// ----------------------------------- // +// Register: default ch3 +// ----------------------------------- // + +// ----------------------------------- // +// Default value for 3rd data channel +// (V/B color) to fill missing pixels +// (when coordinated are out of bound) LSB aligned +// ----------------------------------- // + +#define GDC_DEFAULT_CH3_DEFAULT (0x0) +#define GDC_DEFAULT_CH3_DATASIZE (12) +#define GDC_DEFAULT_CH3_OFFSET (0x78) +#define GDC_DEFAULT_CH3_MASK (0xfff) + +// args: data (12-bit) +static inline void gdc_default_ch3_write(uint16_t data) +{ + uint32_t curr = system_gdc_read_32(0x78L); + uint32_t val = ((data & 0xfff) << 0) | (curr & 0xfffff000); + + system_gdc_write_32(0x78L, val); +} +static inline uint16_t gdc_default_ch3_read(void) +{ + return (uint16_t)((system_gdc_read_32(0x78L) & 0xfff) >> 0); +} +// ----------------------------------- // +// Group: GDC diagnostics +// ----------------------------------- // + +// ----------------------------------- // +// Register: cfg_stall_count0 +// ----------------------------------- // + +// ----------------------------------- // +// Cycles spent on stalls on configutation FIFO to tile reader +// ----------------------------------- // + +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT0_DEFAULT (0x0) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT0_DATASIZE (32) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT0_OFFSET (0x80) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT0_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_diagnostics_cfg_stall_count0_read(void) +{ + return system_gdc_read_32(0x80L); +} +// ----------------------------------- // +// Register: cfg_stall_count1 +// ----------------------------------- // + +// ----------------------------------- // +// Cycles spent on stalls on configutation FIFO to CIM +// ----------------------------------- // + +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT1_DEFAULT (0x0) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT1_DATASIZE (32) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT1_OFFSET (0x84) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT1_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_diagnostics_cfg_stall_count1_read(void) +{ + return system_gdc_read_32(0x84L); +} +// ----------------------------------- // +// Register: cfg_stall_count2 +// ----------------------------------- // + +// ----------------------------------- // +// Cycles spent on stalls on configutation FIFO to PIM +// ----------------------------------- // + +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT2_DEFAULT (0x0) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT2_DATASIZE (32) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT2_OFFSET (0x88) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT2_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_diagnostics_cfg_stall_count2_read(void) +{ + return system_gdc_read_32(0x88L); +} +// ----------------------------------- // +// Register: cfg_stall_count3 +// ----------------------------------- // + +// ----------------------------------- // +// Cycles spent on stalls on configutation FIFO to write cache +// ----------------------------------- // + +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT3_DEFAULT (0x0) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT3_DATASIZE (32) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT3_OFFSET (0x8c) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT3_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_diagnostics_cfg_stall_count3_read(void) +{ + return system_gdc_read_32(0x8cL); +} +// ----------------------------------- // +// Register: cfg_stall_count4 +// ----------------------------------- // + +// ----------------------------------- // +// Cycles spent on stalls on configutation FIFO to tile writer +// ----------------------------------- // + +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT4_DEFAULT (0x0) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT4_DATASIZE (32) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT4_OFFSET (0x90) +#define GDC_DIAGNOSTICS_CFG_STALL_COUNT4_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_diagnostics_cfg_stall_count4_read(void) +{ + return system_gdc_read_32(0x90L); +} +// ----------------------------------- // +// Register: int_read_stall_count +// ----------------------------------- // + +// ----------------------------------- // +// Cycles spent on waiting on pixel interpolator read pixel stream +// ----------------------------------- // + +#define GDC_DIAGNOSTICS_INT_READ_STALL_COUNT_DEFAULT (0x0) +#define GDC_DIAGNOSTICS_INT_READ_STALL_COUNT_DATASIZE (32) +#define GDC_DIAGNOSTICS_INT_READ_STALL_COUNT_OFFSET (0x94) +#define GDC_DIAGNOSTICS_INT_READ_STALL_COUNT_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_diagnostics_int_read_stall_count_read(void) +{ + return system_gdc_read_32(0x94L); +} +// ----------------------------------- // +// Register: int_coord_stall_count +// ----------------------------------- // + +// ----------------------------------- // +// Cycles spent on waiting on coordinate stream of pixel interpolator +// ----------------------------------- // + +#define GDC_DIAGNOSTICS_INT_COORD_STALL_COUNT_DEFAULT (0x0) +#define GDC_DIAGNOSTICS_INT_COORD_STALL_COUNT_DATASIZE (32) +#define GDC_DIAGNOSTICS_INT_COORD_STALL_COUNT_OFFSET (0x98) +#define GDC_DIAGNOSTICS_INT_COORD_STALL_COUNT_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_diagnostics_int_coord_stall_count_read(void) +{ + return system_gdc_read_32(0x98L); +} +// ----------------------------------- // +// Register: int_write_wait_count +// ----------------------------------- // + +// ----------------------------------- // +// Cycles spent on waiting on pixel interpolator output pixel stream +// ----------------------------------- // + +#define GDC_DIAGNOSTICS_INT_WRITE_WAIT_COUNT_DEFAULT (0x0) +#define GDC_DIAGNOSTICS_INT_WRITE_WAIT_COUNT_DATASIZE (32) +#define GDC_DIAGNOSTICS_INT_WRITE_WAIT_COUNT_OFFSET (0x9c) +#define GDC_DIAGNOSTICS_INT_WRITE_WAIT_COUNT_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_diagnostics_int_write_wait_count_read(void) +{ + return system_gdc_read_32(0x9cL); +} +// ----------------------------------- // +// Register: wrt_write_wait_count +// ----------------------------------- // + +// ----------------------------------- // +// Cycles spent on waiting on sending word from write cache to tile writer +// ----------------------------------- // + +#define GDC_DIAGNOSTICS_WRT_WRITE_WAIT_COUNT_DEFAULT (0x0) +#define GDC_DIAGNOSTICS_WRT_WRITE_WAIT_COUNT_DATASIZE (32) +#define GDC_DIAGNOSTICS_WRT_WRITE_WAIT_COUNT_OFFSET (0xa0) +#define GDC_DIAGNOSTICS_WRT_WRITE_WAIT_COUNT_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_diagnostics_wrt_write_wait_count_read(void) +{ + return system_gdc_read_32(0xa0L); +} +// ----------------------------------- // +// Register: int_dual_count +// ----------------------------------- // + +// ----------------------------------- // +// Number of beats on output of tile writer +// interface where 2 pixels were interpolated. +// ----------------------------------- // + +#define GDC_DIAGNOSTICS_INT_DUAL_COUNT_DEFAULT (0x0) +#define GDC_DIAGNOSTICS_INT_DUAL_COUNT_DATASIZE (32) +#define GDC_DIAGNOSTICS_INT_DUAL_COUNT_OFFSET (0xa4) +#define GDC_DIAGNOSTICS_INT_DUAL_COUNT_MASK (0xffffffff) + +// args: data (32-bit) +static inline uint32_t gdc_diagnostics_int_dual_count_read(void) +{ + return system_gdc_read_32(0xa4L); +} +// ----------------------------------------------------// +// Group: AXI Settings +// ----------------------------------------------------// +// ----------------------------------------------------// +// Register: config reader max arlen +// ----------------------------------------------------// +// ----------------------------------------------------// +// Maximum value to use for arlen (axi burst length). +// "0000"= max 1 transfer/burst +// upto "1111"= max 16 transfers/burst +// ----------------------------------------------------// + +#define GDC_AXI_SETTINGS_CONFIG_READER_MAX_ARLEN_DEFAULT (0xF) +#define GDC_AXI_SETTINGS_CONFIG_READER_MAX_ARLEN_DATASIZE (4) +#define GDC_AXI_SETTINGS_CONFIG_READER_MAX_ARLEN_OFFSET (0xa8) +#define GDC_AXI_SETTINGS_CONFIG_READER_MAX_ARLEN_MASK (0xf) + +// args: data (4-bit) +static inline void gdc_axi_settings_config_reader_max_arlen_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0xa8L); + uint32_t val = ((data & 0xf) << 0) | (curr & 0xfffffff0); + + system_gdc_write_32(0xa8L, val); +} +static inline uint8_t gdc_axi_settings_config_reader_max_arlen_read(void) +{ + return (uint8_t)((system_gdc_read_32(0xa8L) & 0xf) >> 0); +} +// ----------------------------------- // +// Register: config reader fifo watermark +// ----------------------------------- // + +// ----------------------------------- // +// Number of words space in fifo before AXI read burst(s) start +// (legal values = max_burst_length(max_arlen+1) +// to 2**fifo_aw, but workable value +// for your system are probably less!). +// Allowing n back to back bursts to generated +// if watermark is set to n*burst length. +// Burst(s) continue while fifo has enough space for next burst. +// ----------------------------------- // + +#define GDC_AXI_SETTINGS_CONFIG_READER_FIFO_WATERMARK_DEFAULT (0x10) +#define GDC_AXI_SETTINGS_CONFIG_READER_FIFO_WATERMARK_DATASIZE (8) +#define GDC_AXI_SETTINGS_CONFIG_READER_FIFO_WATERMARK_OFFSET (0xa8) +#define GDC_AXI_SETTINGS_CONFIG_READER_FIFO_WATERMARK_MASK (0xff00) + +// args: data (8-bit) +static inline void +gdc_axi_settings_config_reader_fifo_watermark_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0xa8L); + uint32_t val = ((data & 0xff) << 8) | (curr & 0xffff00ff); + + system_gdc_write_32(0xa8L, val); +} +static inline uint8_t gdc_axi_settings_config_reader_fifo_watermark_read(void) +{ + return (uint8_t)((system_gdc_read_32(0xa8L) & 0xff00) >> 8); +} +// ----------------------------------- // +// Register: config reader rxact maxostand +// ----------------------------------- // +// ----------------------------------- // +// Max outstanding read transactions (bursts) allowed. +// zero means no maximum(uses fifo size as max) +// ----------------------------------- // + +#define GDC_AXI_SETTINGS_CONFIG_READER_RXACT_MAXOSTAND_DEFAULT (0x00) +#define GDC_AXI_SETTINGS_CONFIG_READER_RXACT_MAXOSTAND_DATASIZE (8) +#define GDC_AXI_SETTINGS_CONFIG_READER_RXACT_MAXOSTAND_OFFSET (0xa8) +#define GDC_AXI_SETTINGS_CONFIG_READER_RXACT_MAXOSTAND_MASK (0xff0000) + +// args: data (8-bit) +static inline void +gdc_axi_settings_config_reader_rxact_maxostand_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0xa8L); + uint32_t val = ((data & 0xff) << 16) | (curr & 0xff00ffff); + + system_gdc_write_32(0xa8L, val); +} +static inline uint8_t gdc_axi_settings_config_reader_rxact_maxostand_read(void) +{ + return (uint8_t)((system_gdc_read_32(0xa8L) & 0xff0000) >> 16); +} +// ----------------------------------- // +// Register: tile reader max arlen +// ----------------------------------- // + +// ----------------------------------- // +// Maximum value to use for arlen (axi burst length). +// "0000"= max 1 transfer/burst , upto "1111"= max 16 transfers/burst +// ----------------------------------- // + +#define GDC_AXI_SETTINGS_TILE_READER_MAX_ARLEN_DEFAULT (0xF) +#define GDC_AXI_SETTINGS_TILE_READER_MAX_ARLEN_DATASIZE (4) +#define GDC_AXI_SETTINGS_TILE_READER_MAX_ARLEN_OFFSET (0xac) +#define GDC_AXI_SETTINGS_TILE_READER_MAX_ARLEN_MASK (0xf) + +// args: data (4-bit) +static inline void gdc_axi_settings_tile_reader_max_arlen_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0xacL); + uint32_t val = ((data & 0xf) << 0) | (curr & 0xfffffff0); + + system_gdc_write_32(0xacL, val); +} +static inline uint8_t gdc_axi_settings_tile_reader_max_arlen_read(void) +{ + return (uint8_t)((system_gdc_read_32(0xacL) & 0xf) >> 0); +} +// ----------------------------------- // +// Register: tile reader fifo watermark +// ----------------------------------- // + +// ----------------------------------- // +// Number of words space in fifo before AXI read burst(s) start +// (legal values = max_burst_length(max_arlen+1) to 2**fifo_aw, +// but workable value for your system are probably less!). +// Allowing n back to back bursts to generated +// if watermark is set to n*burst length. +// Burst(s) continue while fifo has enough space for next burst. +// ----------------------------------- // + +#define GDC_AXI_SETTINGS_TILE_READER_FIFO_WATERMARK_DEFAULT (0x10) +#define GDC_AXI_SETTINGS_TILE_READER_FIFO_WATERMARK_DATASIZE (8) +#define GDC_AXI_SETTINGS_TILE_READER_FIFO_WATERMARK_OFFSET (0xac) +#define GDC_AXI_SETTINGS_TILE_READER_FIFO_WATERMARK_MASK (0xff00) + +// args: data (8-bit) +static inline void +gdc_axi_settings_tile_reader_fifo_watermark_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0xacL); + uint32_t val = ((data & 0xff) << 8) | (curr & 0xffff00ff); + + system_gdc_write_32(0xacL, val); +} +static inline uint8_t gdc_axi_settings_tile_reader_fifo_watermark_read(void) +{ + return (uint8_t)((system_gdc_read_32(0xacL) & 0xff00) >> 8); +} +// ----------------------------------- // +// Register: tile reader rxact maxostand +// ----------------------------------- // + +// ----------------------------------- // +// Max outstanding read transactions +// (bursts) allowed. zero means no maximum(uses fifo size as max). +// ----------------------------------- // + +#define GDC_AXI_SETTINGS_TILE_READER_RXACT_MAXOSTAND_DEFAULT (0x00) +#define GDC_AXI_SETTINGS_TILE_READER_RXACT_MAXOSTAND_DATASIZE (8) +#define GDC_AXI_SETTINGS_TILE_READER_RXACT_MAXOSTAND_OFFSET (0xac) +#define GDC_AXI_SETTINGS_TILE_READER_RXACT_MAXOSTAND_MASK (0xff0000) + +// args: data (8-bit) +static inline void +gdc_axi_settings_tile_reader_rxact_maxostand_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0xacL); + uint32_t val = ((data & 0xff) << 16) | (curr & 0xff00ffff); + + system_gdc_write_32(0xacL, val); +} +static inline uint8_t gdc_axi_settings_tile_reader_rxact_maxostand_read(void) +{ + return (uint8_t)((system_gdc_read_32(0xacL) & 0xff0000) >> 16); +} +// ----------------------------------- // +// Register: tile writer max awlen +// ----------------------------------- // + +// ----------------------------------- // +// Maximum value to use for awlen (axi burst length). +// "0000"= max 1 transfer/burst , upto "1111"= max 16 transfers/burst +// ----------------------------------- // + +#define GDC_AXI_SETTINGS_TILE_WRITER_MAX_AWLEN_DEFAULT (0xF) +#define GDC_AXI_SETTINGS_TILE_WRITER_MAX_AWLEN_DATASIZE (4) +#define GDC_AXI_SETTINGS_TILE_WRITER_MAX_AWLEN_OFFSET (0xb0) +#define GDC_AXI_SETTINGS_TILE_WRITER_MAX_AWLEN_MASK (0xf) + +// args: data (4-bit) +static inline void gdc_axi_settings_tile_writer_max_awlen_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0xb0L); + uint32_t val = ((data & 0xf) << 0) | (curr & 0xfffffff0); + + system_gdc_write_32(0xb0L, val); +} +static inline uint8_t gdc_axi_settings_tile_writer_max_awlen_read(void) +{ + return (uint8_t)((system_gdc_read_32(0xb0L) & 0xf) >> 0); +} +// ----------------------------------- // +// Register: tile writer fifo watermark +// ----------------------------------- // + +// ----------------------------------- // +// Number of words in fifo before AXI write burst(s) start +// (legal values = max_burst_length(max_awlen+1) to 2**fifo_aw, +// but workable value for your system are probably less!). +// Allowing n back to back bursts to generated +// if watermark is set to n*burst length. +// Burst(s) continue while fifo has enough for next burst. +// ----------------------------------- // + +#define GDC_AXI_SETTINGS_TILE_WRITER_FIFO_WATERMARK_DEFAULT (0x10) +#define GDC_AXI_SETTINGS_TILE_WRITER_FIFO_WATERMARK_DATASIZE (8) +#define GDC_AXI_SETTINGS_TILE_WRITER_FIFO_WATERMARK_OFFSET (0xb0) +#define GDC_AXI_SETTINGS_TILE_WRITER_FIFO_WATERMARK_MASK (0xff00) + +// args: data (8-bit) +static inline void +gdc_axi_settings_tile_writer_fifo_watermark_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0xb0L); + uint32_t val = ((data & 0xff) << 8) | (curr & 0xffff00ff); + + system_gdc_write_32(0xb0L, val); +} +static inline uint8_t +gdc_axi_settings_tile_writer_fifo_watermark_read(void) +{ + return (uint8_t)((system_gdc_read_32(0xb0L) & 0xff00) >> 8); +} +// ----------------------------------- // +// Register: tile writer wxact maxostand +// ----------------------------------- // + +// ----------------------------------- // +// Max outstanding write transactions (bursts) +// allowed. zero means no maximum(uses internal limit of 2048) +// ----------------------------------- // + +#define GDC_AXI_SETTINGS_TILE_WRITER_WXACT_MAXOSTAND_DEFAULT (0x00) +#define GDC_AXI_SETTINGS_TILE_WRITER_WXACT_MAXOSTAND_DATASIZE (8) +#define GDC_AXI_SETTINGS_TILE_WRITER_WXACT_MAXOSTAND_OFFSET (0xb0) +#define GDC_AXI_SETTINGS_TILE_WRITER_WXACT_MAXOSTAND_MASK (0xff0000) + +// args: data (8-bit) +static inline void +gdc_axi_settings_tile_writer_wxact_maxostand_write(uint8_t data) +{ + uint32_t curr = system_gdc_read_32(0xb0L); + uint32_t val = ((data & 0xff) << 16) | (curr & 0xff00ffff); + + system_gdc_write_32(0xb0L, val); +} +static inline uint8_t gdc_axi_settings_tile_writer_wxact_maxostand_read(void) +{ + return (uint8_t)((system_gdc_read_32(0xb0L) & 0xff0000) >> 16); +} +// ----------------------------------- // +#endif //__GDC_CONFIG_H__ diff --git a/drivers/amlogic/media/gdc/inc/sys/system_gdc_io.h b/drivers/amlogic/media/gdc/inc/sys/system_gdc_io.h new file mode 100644 index 0000000..097271d --- /dev/null +++ b/drivers/amlogic/media/gdc/inc/sys/system_gdc_io.h @@ -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__ */ diff --git a/drivers/amlogic/media/gdc/inc/sys/system_log.h b/drivers/amlogic/media/gdc/inc/sys/system_log.h new file mode 100644 index 0000000..8b9e459 --- /dev/null +++ b/drivers/amlogic/media/gdc/inc/sys/system_log.h @@ -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 +#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__ diff --git a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c new file mode 100644 index 0000000..6900f42 --- /dev/null +++ b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c @@ -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 +#include +#include +#include +#include +#include + +//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; +} diff --git a/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c b/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c new file mode 100644 index 0000000..378789f --- /dev/null +++ b/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c @@ -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 +#include +#include +#include + +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); +} diff --git a/drivers/amlogic/media/gdc/src/platform/system_log.c b/drivers/amlogic/media/gdc/src/platform/system_log.c new file mode 100644 index 0000000..0f06e87 --- /dev/null +++ b/drivers/amlogic/media/gdc/src/platform/system_log.c @@ -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"}; -- 2.7.4