From 8e4bff4cab0ddac6060645b0715210484d02ff40 Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Wed, 30 Aug 2017 08:25:59 +0000 Subject: Initial file dump from open source release --- drivers/autotst/Kconfig | 3 + drivers/autotst/Makefile | 22 + drivers/autotst/autotstdrv.c | 440 +++++++++ drivers/autotst/autotstdrv.h | 87 ++ drivers/autotst/dispc.c | 1221 +++++++++++++++++++++++++ drivers/autotst/dispc.h | 42 + drivers/autotst/dispc_reg.h | 136 +++ drivers/autotst/dsi.c | 477 ++++++++++ drivers/autotst/lcd_dummy.c | 109 +++ drivers/autotst/lcd_dummy.h | 125 +++ drivers/autotst/lcdc.c | 114 +++ drivers/autotst/lcdc_reg.h | 95 ++ drivers/autotst/mipi_dsih_api.c | 1708 +++++++++++++++++++++++++++++++++++ drivers/autotst/mipi_dsih_api.h | 134 +++ drivers/autotst/mipi_dsih_dphy.c | 1082 ++++++++++++++++++++++ drivers/autotst/mipi_dsih_dphy.h | 67 ++ drivers/autotst/mipi_dsih_hal.c | 1114 +++++++++++++++++++++++ drivers/autotst/mipi_dsih_hal.h | 1804 +++++++++++++++++++++++++++++++++++++ drivers/autotst/mipi_dsih_local.h | 362 ++++++++ drivers/autotst/pinmap_gpio.h | 116 +++ 20 files changed, 9258 insertions(+) create mode 100644 drivers/autotst/Kconfig create mode 100644 drivers/autotst/Makefile create mode 100644 drivers/autotst/autotstdrv.c create mode 100644 drivers/autotst/autotstdrv.h create mode 100644 drivers/autotst/dispc.c create mode 100644 drivers/autotst/dispc.h create mode 100644 drivers/autotst/dispc_reg.h create mode 100644 drivers/autotst/dsi.c create mode 100644 drivers/autotst/lcd_dummy.c create mode 100644 drivers/autotst/lcd_dummy.h create mode 100644 drivers/autotst/lcdc.c create mode 100644 drivers/autotst/lcdc_reg.h create mode 100644 drivers/autotst/mipi_dsih_api.c create mode 100644 drivers/autotst/mipi_dsih_api.h create mode 100644 drivers/autotst/mipi_dsih_dphy.c create mode 100644 drivers/autotst/mipi_dsih_dphy.h create mode 100644 drivers/autotst/mipi_dsih_hal.c create mode 100644 drivers/autotst/mipi_dsih_hal.h create mode 100644 drivers/autotst/mipi_dsih_local.h create mode 100644 drivers/autotst/pinmap_gpio.h (limited to 'drivers/autotst') diff --git a/drivers/autotst/Kconfig b/drivers/autotst/Kconfig new file mode 100644 index 00000000..eedfb46c --- /dev/null +++ b/drivers/autotst/Kconfig @@ -0,0 +1,3 @@ +config HAS_AUTOTST + boolean + default n diff --git a/drivers/autotst/Makefile b/drivers/autotst/Makefile new file mode 100644 index 00000000..97135f3a --- /dev/null +++ b/drivers/autotst/Makefile @@ -0,0 +1,22 @@ + +ifneq ($(KERNELRELEASE),) + + autotst-objs := autotstdrv.o dispc.o dsi.o lcd_dummy.o mipi_dsih_api.o mipi_dsih_dphy.o mipi_dsih_hal.o + obj-m := autotst.o + +else + PRJ_ROOT=/home/anli/andr4 + export ARCH=arm + export CROSS_COMPILE=${PRJ_ROOT}/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi- + KNRL_DIR=${PRJ_ROOT}/out/target/product/sp8810gb/obj/KERNEL + +all: + make -C ${KNRL_DIR} M=`pwd` $@ + +clean: + @rm -rf *.o .*.o.cmd *.mod.c *.ko .*.ko.cmd *.order *.symvers Makefile~ .tmp_versions + +#@rmdir .tmp_versions + +endif + diff --git a/drivers/autotst/autotstdrv.c b/drivers/autotst/autotstdrv.c new file mode 100644 index 00000000..be14b956 --- /dev/null +++ b/drivers/autotst/autotstdrv.c @@ -0,0 +1,440 @@ +// ****************************************** // +// access IIC, GPIO, etc. from user space by anli.wei +// 2012-11-25 +// 2013-01-22 add key info anli.wei +// ****************************************** // + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +// +#include "autotstdrv.h" +#include "dispc.h" +// +#define DBG_ENABLE_FUN +#define DBG_ENABLE_INFO + +#ifdef DBG_ENABLE_FUN +#define FUN_ENTER printk(KERN_INFO "autotst-> %s ++.\n", __FUNCTION__) +#define FUN_LEAVE printk(KERN_INFO "autotst-> %s --.\n", __FUNCTION__) +#else +#define FUN_ENTER do {} while(0) +#define FUN_LEAVE do {} while(0) +#endif // DBG_ENABLE_FUN + +#ifdef DBG_ENABLE_INFO +#define DBG_INFO(fmt, arg...) printk(KERN_INFO "autotst-> " fmt, ##arg) +#else +#define DBG_INFO(fmt, arg...) do {} while(0) +#endif // DBG_ENABLE_INFO + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +#define SPRD_MAX_PIN 200 +#define SPRD_GPIO_PIN_INVALID_VALUE 0xFFFFFFFF + +//static uint32_t sGpioPins[SPRD_MAX_PIN]; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +extern int lcm_init( void ); +extern int32_t lcm_send_data (uint32_t data); + +//------------------------------------------------------------------------------ +#define CDEV_NAME "autotst" + +static dev_t s_devt; +static struct cdev s_cdev; +static struct class *s_class; + +//------------------------------------------------------------------------------ + +static int autotst_open (struct inode *inode, struct file *filp) +{ + FUN_ENTER; + FUN_LEAVE; + return 0; +} + +static int autotst_release (struct inode *inode, struct file *filp) +{ + FUN_ENTER; + FUN_LEAVE; + return 0; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +static int i2c_read( struct autotst_i2c_info_t * info ) +{ + struct i2c_msg xfer[2]; + u8 reg[2], reg_len = 0; + u8 addr = (info->addr >> 1); + int ret; + + struct i2c_adapter * adpt = i2c_get_adapter(info->bus); + if( NULL == adpt ) { + printk(KERN_ERR "get adapter(%d) fail!\n", info->bus); + return -ENXIO; + } + + DBG_INFO("i2c read: bus = %d, addr = %X, reg = %X\n", info->bus, addr, info->reg); + + if( 16 == info->regBits ) { + reg[reg_len++] = (u8)(info->reg >> 8); + } + reg[reg_len++] = (u8)(info->reg); + + // Write address + xfer[0].addr = addr; + xfer[0].flags = 0; + xfer[0].len = reg_len; + xfer[0].buf = reg; + + /* Read data */ + xfer[1].addr = addr; + xfer[1].flags = I2C_M_RD; + xfer[1].len = info->data_len; + xfer[1].buf = info->data; + + ret = i2c_transfer(adpt, xfer, 2); + if( ret < 0 ) { + printk(KERN_ERR "i2c_transfer() returned %d\n", ret); + + i2c_put_adapter(adpt); + return ret; + } + + DBG_INFO("i2c read done: bus = %d, addr = 0x%04X, reg = 0x%04X\n", + info->bus, info->addr, info->reg); + + i2c_put_adapter(adpt); + return 0; +} + +//------------------------------------------------------------------------------ +static int i2c_write( struct autotst_i2c_info_t * info ) +{ + u8 buf[64]; + u8 num = 0; + int ret, i; + + struct i2c_msg xfer; + + struct i2c_adapter * adpt = i2c_get_adapter(info->bus); + if( NULL == adpt ) { + printk(KERN_ERR "get adapter(%d) fail!\n", info->bus); + return -ENXIO; + } + + if( 16 == info->regBits ) { + buf[num++] = (u8)(info->reg >> 8); + } + + buf[num++] = (u8)(info->reg); + + for( i = 0; i < info->data_len; ++i ) + { + buf[num++] = info->data[i]; + } + + xfer.addr = info->addr; + xfer.flags = 0; + xfer.len = num; + xfer.buf = buf; + + ret = i2c_transfer(adpt, &xfer, 1); + if( ret < 0 ) { + printk(KERN_ERR "i2c_transfer() returned %d\n", ret); + + i2c_put_adapter(adpt); + return ret; + } + + DBG_INFO("i2c write done: bus = %d, addr = 0x%04X, reg = 0x%04X\n", + info->bus, info->addr, info->reg); + + i2c_put_adapter(adpt); + return 0; +} + +//------------------------------------------------------------------------------ +static int i2c_ioctl( unsigned int cmd, unsigned long arg ) +{ + int ret = 0; + struct autotst_i2c_info_t iit; + + if( copy_from_user(&iit, (const void __user *)arg, sizeof(struct autotst_i2c_info_t)) ) { + printk(KERN_ERR "copy_from_user fail: arg = %lu\n", arg); + return -EFAULT; + } + + switch( cmd ) { + case AUTOTST_IOCTL_I2C_READ: + ret = i2c_read( &iit ); + if( ret == 0 ) { + if( copy_to_user((void __user *)arg, &iit, sizeof(struct autotst_i2c_info_t)) ) { + printk(KERN_ERR "copy_to_user fail: arg = %lu\n", arg); + ret = -EFAULT; + } + } + break; + case AUTOTST_IOCTL_I2C_WRITE: + ret = i2c_write( &iit ); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +static int gpio_ioctl( unsigned int cmd, unsigned long arg ) +{ + int ret = 0; + int pull = 0; + struct autotst_gpio_info_t git; + + if( copy_from_user(&git, (const void __user *)arg, sizeof(struct autotst_gpio_info_t)) ) { + printk(KERN_ERR "copy_from_user fail: arg = %lu\n", arg); + return -EFAULT; + } + + switch( cmd ) { + case AUTOTST_IOCTL_GPIO_INIT: + { + char name[32]; + snprintf(name, 32, "at_gio_%d", git.gpio); +/* // not support, already config on platform + if( git.pup_enb ) { + } + if( git.pdwn_enb ) { + } +*/ + pull = ( (git.pdwn_enb << 6) & (BIT_PIN_WPD) ) | ((git.pup_enb << 7) & (BIT_PIN_WPU)); + autotst_pin_ctrl(DISPC_PIN_FUNC3, git.gpio, pull); + gpio_request(git.gpio, name); + if( AUTOTST_GPIO_DIR_IN == git.dir ) { + gpio_direction_input(git.gpio); + } else { + gpio_direction_output(git.gpio, git.val); + } + } + break; + case AUTOTST_IOCTL_GPIO_GET: { + int gv = gpio_get_value(git.gpio); + + git.val = (gv > 0) ? 1 : 0; + if( copy_to_user((void __user *)arg, &git, sizeof(struct autotst_gpio_info_t)) ) { + printk(KERN_ERR "copy_to_user fail: arg = %lu\n", arg); + ret = -EFAULT; + } + } + break; + case AUTOTST_IOCTL_GPIO_SET: + gpio_set_value(git.gpio, git.val); + break; + case AUTOTST_IOCTL_GPIO_CLOSE: + autotst_pin_ctrl(DISPC_PIN_FUNC0, git.gpio, pull); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +static int key_ioctl( unsigned int cmd, unsigned long arg ) +{ + int ret = 0; + struct autotst_key_info_t kit; + + if( copy_from_user(&kit, (const void __user *)arg, sizeof(struct autotst_key_info_t)) ) { + printk(KERN_ERR "copy_from_user fail: arg = %lu\n", arg); + return -EFAULT; + } + + if( KEY_POWER == kit.val ) { + kit.row = AUTOTST_KEY_INVALID_ROW; + kit.col = AUTOTST_KEY_INVALID_COL; + kit.gio = EIC_KEY_POWER; + } else { + unsigned char rc = (kit.val & 0xF7); + + kit.row = ((rc >> 4) & 0x0F); + kit.col = ((rc >> 0) & 0x0F); + kit.gio = 0; + } + + if( 0 == ret ) { + if( copy_to_user((void __user *)arg, &kit, sizeof(struct autotst_key_info_t)) ) { + printk(KERN_ERR "copy_to_user fail: arg = %lu\n", arg); + ret = -EFAULT; + } + } + + return ret; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +static long autotst_ioctl( struct file *filp, unsigned int cmd, unsigned long arg ) +{ + long ret = -1; + + FUN_ENTER; + + DBG_INFO("cmd = 0x%X\n", cmd); + switch( cmd ) { + case AUTOTST_IOCTL_I2C_READ: + case AUTOTST_IOCTL_I2C_WRITE: + ret = i2c_ioctl(cmd, arg); + break; + case AUTOTST_IOCTL_GPIO_INIT: + case AUTOTST_IOCTL_GPIO_GET: + case AUTOTST_IOCTL_GPIO_SET: + case AUTOTST_IOCTL_GPIO_CLOSE: + ret = gpio_ioctl(cmd, arg); + break; + case AUTOTST_IOCTL_LCD_DATA: + { + int i; + DBG_INFO("lcd data = 0x%X\n", (uint32_t)arg); +#if 0 + lcm_init(); + for( i = 0; i < 32; ++i ) { + lcm_send_data((uint32_t)arg); + } +#else + autotst_dispc_init(DISPLAY_TYPE_MCU); + for( i = 0; i < 32; ++i ) { + autotst_dispc_mcu_send_data((uint32_t)arg); + } + autotst_dispc_uninit(DISPLAY_TYPE_MCU); +#endif + ret = 0; + } + break; +#if 1 + case AUTOTST_IOCTL_LCD_MIPI_ON: + { + int i; + DBG_INFO("lcd mipi on\n"); + autotst_dispc_init(DISPLAY_TYPE_MIPI); + autotst_dispc_refresh(); + ret = 0; + } + break; + case AUTOTST_IOCTL_LCD_MIPI_OFF: + { + int i; + DBG_INFO("lcd mipi off\n"); + autotst_dispc_uninit(DISPLAY_TYPE_MIPI); + ret = 0; + } + break; +#endif + case AUTOTST_IOCTL_GET_KEYINFO: + ret = key_ioctl(cmd, arg); + break; + default: + ret = -EINVAL; + DBG_INFO("lcd default \n"); + break; + } + + FUN_LEAVE; + return ret; +} + +static struct file_operations autotst_fops = +{ + .owner = THIS_MODULE, + .unlocked_ioctl = autotst_ioctl, + .open = autotst_open, + .release = autotst_release, +}; + +//============================================================================== + +static int __init autotst_init(void) +{ + int ret; + + FUN_ENTER; + + // auto select a major + ret = alloc_chrdev_region(&s_devt, 0, 1, CDEV_NAME); + if( ret < 0 ) { + printk(KERN_ERR "ERROR: alloc_chrdev_region %d\n", ret); + return ret; + } + + cdev_init(&s_cdev, &autotst_fops); + ret = cdev_add(&s_cdev, s_devt, 1); + if( ret < 0 ) + { + unregister_chrdev_region(s_devt, 1); + printk(KERN_ERR "ERROR: cdev_add %d\n", ret); + return ret; + } + + s_class = class_create(THIS_MODULE, CDEV_NAME); + device_create(s_class, NULL, MKDEV(MAJOR(s_devt), MINOR(s_devt)), NULL, CDEV_NAME); + +// autotst_dispc_pin_ctrl(DISPC_PIN_FUNC3); + + //for( i = 0; i < SPRD_MAX_PIN; ++i ) { + // sGpioPins[i] = SPRD_GPIO_PIN_INVALID_VALUE; + //} + //sGpioPins[59] = MFP_CFG_X(SIMCLK3, AF3, DS1, F_PULL_NONE, S_PULL_NONE, IO_OE); + + FUN_LEAVE; + return 0; +} + +static void __exit autotst_exit(void) +{ + FUN_ENTER; + + device_destroy(s_class, MKDEV(MAJOR(s_devt), MINOR(s_devt))); + class_destroy(s_class); + + cdev_del(&s_cdev); + unregister_chrdev_region(s_devt, 1); + +// autotst_dispc_pin_ctrl(DISPC_PIN_FUNC0); + + FUN_LEAVE; +} + +module_init(autotst_init); +module_exit(autotst_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("anli.wei"); +MODULE_VERSION("0.0.1"); diff --git a/drivers/autotst/autotstdrv.h b/drivers/autotst/autotstdrv.h new file mode 100644 index 00000000..48cb8f6e --- /dev/null +++ b/drivers/autotst/autotstdrv.h @@ -0,0 +1,87 @@ + +#ifndef _AUTOTSTDRV_20130207_H__ +#define _AUTOTSTDRV_20130207_H__ + +//----------------------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus +//----------------------------------------------------------------------------- + +#include + +// +//------------------------------------------------------------------------------ +// +#define AUTOTST_IOCTL_MAGIC 'A' + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +struct autotst_i2c_info_t { + unsigned char bus; + unsigned char rcv0; + unsigned short addr; + + unsigned short reg; + unsigned char regBits; // 8 or 16 + unsigned char rcv1; + + unsigned char rcv2; + unsigned char data_len; + unsigned char data[16]; + +}; + +// +#define AUTOTST_IOCTL_I2C_READ _IOWR(AUTOTST_IOCTL_MAGIC, 0x00, struct autotst_i2c_info_t) +#define AUTOTST_IOCTL_I2C_WRITE _IOWR(AUTOTST_IOCTL_MAGIC, 0x01, struct autotst_i2c_info_t) + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +#define AUTOTST_GPIO_DIR_IN 0 +#define AUTOTST_GPIO_DIR_OUT 1 + +struct autotst_gpio_info_t { + unsigned short gpio; + unsigned char dir; + unsigned char val; + unsigned char pup_enb; + unsigned char pup; + unsigned char pdwn_enb; + unsigned char pdwn; +}; + +#define AUTOTST_IOCTL_GPIO_INIT _IOWR(AUTOTST_IOCTL_MAGIC, 0x10, struct autotst_gpio_info_t) +#define AUTOTST_IOCTL_GPIO_GET _IOWR(AUTOTST_IOCTL_MAGIC, 0x11, struct autotst_gpio_info_t) +#define AUTOTST_IOCTL_GPIO_SET _IOW (AUTOTST_IOCTL_MAGIC, 0x12, struct autotst_gpio_info_t) +#define AUTOTST_IOCTL_GPIO_CLOSE _IOW (AUTOTST_IOCTL_MAGIC, 0x13, struct autotst_gpio_info_t) + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +#define AUTOTST_LCD_DATA_NUM 32 +#define AUTOTST_IOCTL_LCD_DATA _IOW (AUTOTST_IOCTL_MAGIC, 0x30, int) +#define AUTOTST_IOCTL_LCD_MIPI_ON _IOW (AUTOTST_IOCTL_MAGIC, 0x31, int) +#define AUTOTST_IOCTL_LCD_MIPI_OFF _IOW (AUTOTST_IOCTL_MAGIC, 0x32, int) + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +#define AUTOTST_KEY_INVALID_ROW 0xFFEE +#define AUTOTST_KEY_INVALID_COL 0xFFEE + +struct autotst_key_info_t { + unsigned short val; // key value + unsigned short row; // + unsigned short col; + unsigned short gio; +}; + +#define AUTOTST_IOCTL_GET_KEYINFO _IOWR(AUTOTST_IOCTL_MAGIC, 0x40, struct autotst_key_info_t) + + +//----------------------------------------------------------------------------- +#ifdef __cplusplus +} +#endif // __cplusplus +//----------------------------------------------------------------------------- + +#endif // _AUTOTSTDRV_20130207_H__ diff --git a/drivers/autotst/dispc.c b/drivers/autotst/dispc.c new file mode 100644 index 00000000..763be07e --- /dev/null +++ b/drivers/autotst/dispc.c @@ -0,0 +1,1221 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 "dispc_reg.h" +#include "lcd_dummy.h" +#include "dispc.h" +#include "pinmap_gpio.h" + +#define pr_debug printk + +#ifdef CONFIG_FB_SCX15 +#define DISPC_CLOCK_PARENT ("clk_192m") +#define DISPC_CLOCK (192*1000000) +#define DISPC_DBI_CLOCK_PARENT ("clk_256m") +#define DISPC_DBI_CLOCK (256*1000000) +#define DISPC_DPI_CLOCK_PARENT ("clk_192m") +#define SPRDFB_DPI_CLOCK_SRC (192000000) +#define DISPC_DPI_CLOCK (192*1000000/18) +#else +#define DISPC_CLOCK_PARENT ("clk_256m") +#define DISPC_CLOCK (256*1000000) +#define DISPC_DBI_CLOCK_PARENT ("clk_256m") +#define DISPC_DBI_CLOCK (256*1000000) +#define DISPC_DPI_CLOCK_PARENT ("clk_384m") +#define SPRDFB_DPI_CLOCK_SRC (384000000) +#define DISPC_DPI_CLOCK (384*1000000/36) +#endif + +#define DISPC_EMC_EN_PARENT ("clk_aon_apb") + +#if ((defined CONFIG_FB_SCX30G)||(defined CONFIG_FB_SCX35L)) +#define DISPC_PLL_CLK ("clk_dispc0") +#define DISPC_DBI_CLK ("clk_dispc0_dbi") +#define DISPC_DPI_CLK ("clk_dispc0_dpi") +#else +#define DISPC_PLL_CLK ("clk_disc0") +#define DISPC_DBI_CLK ("clk_disc0_dbi") +#define DISPC_DPI_CLK ("clk_disc0_dpi") +#endif +#define DISPC_EMC_CLK ("clk_disp_emc") + +#define PATTEN_GRID_WIDTH (40) +#define PATTEN_GRID_HEIGHT (40) +#define PATTEN_COLOR_COUNT (7) + +extern struct panel_spec lcd_dummy_mipi_spec; +extern struct panel_spec lcd_dummy_rgb_spec; +extern struct panel_spec lcd_dummy_mcu_spec; + +extern void autotst_dsi_dump(void); +extern void autotst_dsi_dump1(void); +extern int32_t autotst_dsi_init(struct panel_spec *panel); +extern int32_t autotst_dsi_uninit(void); + +struct autotst_dispc_context { + struct clk *clk_dispc; + struct clk *clk_dispc_dpi; + struct clk *clk_dispc_dbi; + struct clk *clk_dispc_emc; + uint32_t fb_addr_v; + uint32_t fb_addr_p; + uint32_t fb_size; + uint32_t dispc_if; + bool is_inited; +}; + +static struct autotst_dispc_context autotst_dispc_ctx = {0}; +static struct panel_spec *autotst_panel = NULL; + +static uint32_t g_patten_table[PATTEN_COLOR_COUNT] = + {0xffff0000, 0xff00ff00, 0xff0000ff, 0xffffff00, 0xff00ffff, 0xffff00ff, 0xffffffff}; + +unsigned long sprd_adi_base; + +#if 0 /*designed for RGB, not used for SHARKL*/ +int autotst_dispc_pin_ctrl(int type) +{ + static int pin_table[29]; + static int is_first_time = true; + int i; + u32 regs = REG_PIN_LCD_CSN1; + u32 func; + + if (is_first_time) { + for (i = 0; i < 29; ++i) { + pin_table[i] = pinmap_get(regs); + regs += 4; + } + is_first_time = false; + } + + if (type == DISPC_PIN_FUNC3) + func = BITS_PIN_DS(1) | BITS_PIN_AF(DISPC_PIN_FUNC3) | BIT_PIN_SLP_AP; + else { + pr_err("The function hasn't been implemented yet\n"); + return 0; + } + + regs = REG_PIN_LCD_CSN1; + for (i = 0; i < 29; ++i) { + if (type == DISPC_PIN_FUNC0) + pinmap_set(regs, pin_table[i]); + else + pinmap_set(regs, func); + regs += 4; + } + + return 0; +} +#endif + +int autotst_pin_ctrl(int type, int gpio_num, int gpio_pull) +{ + static int pin_table; + int i; + u32 regs = REG_PIN_U0TXD; + u32 func; + u32 mask; +#ifdef CONFIG_REGULATOR_SC2713S + mask = BIT_LDO_SD_PD | BIT_LDO_SIM0_PD | BIT_LDO_SIM1_PD | BIT_LDO_SIM2_PD | BIT_LDO_CAMA_PD |\ + BIT_LDO_CAMD_PD | BIT_LDO_CAMIO_PD | BIT_LDO_CAMMOT_PD; + + ANA_REG_BIC(ANA_REG_GLB_LDO_PD_CTRL, mask); + + for (i = 0; i < ARRAY_SIZE(pinmap_gpio); ++i) { + if( gpio_num == pinmap_gpio[i].num){ + regs = pinmap_gpio[i].reg; + pin_table = pinmap_get(regs); + break; + } + } + + if (type == DISPC_PIN_FUNC3){ + func = BITS_PIN_DS(1) | BITS_PIN_AF(DISPC_PIN_FUNC3) | BIT_PIN_SLP_AP | gpio_pull; + }else { + pr_err("The function hasn't been implemented yet\n"); + } + + if (type == DISPC_PIN_FUNC0){ + pinmap_set(regs, pin_table); + }else{ + pinmap_set(regs, func); + } +#endif + return 0; +} + +/**********************************************/ +/* MCU PANEL CONFIG */ +/**********************************************/ +static uint32_t mcu_calc_timing(struct timing_mcu *timing) +{ + uint32_t clk_rate; + uint32_t rcss, rlpw, rhpw, wcss, wlpw, whpw; + struct clk * clk = NULL; + + if(NULL == timing){ + printk(KERN_ERR "autotst_dispc: [%s]: Invalid Param\n", __FUNCTION__); + return 0; + } + + clk = clk_get(NULL,"clk_dispc_dbi"); + if (IS_ERR(clk)) { + printk(KERN_WARNING "autotst_dispc: get clk_dispc_dbi fail!\n"); + } else { + pr_debug(KERN_INFO "autotst_dispc: get clk_dispc_dbi ok!\n"); + } +// clk_rate = clk_get_rate(clk) / 1000000; + clk_rate = 250; // dummy 250M Hz + + pr_debug(KERN_INFO "autotst_dispc: [%s] clk_rate: 0x%x\n", __FUNCTION__, clk_rate); + + /******************************************************** + * we assume : t = ? ns, dispc_dbi = ? MHz so + * 1ns need cycle : dispc_dbi /1000 + * tns need cycles : t * dispc_dbi / 1000 + * + ********************************************************/ +#define MAX_DBI_RWCSS_TIMING_VALUE 15 +#define MAX_DBI_RWLPW_TIMING_VALUE 63 +#define MAX_DBI_RWHPW_TIMING_VALUE 63 +#define DBI_CYCLES(ns) (( (ns) * clk_rate + 1000 - 1)/ 1000) + + /* ceiling*/ + rcss = DBI_CYCLES(timing->rcss); + if (rcss > MAX_DBI_RWCSS_TIMING_VALUE) { + rcss = MAX_DBI_RWCSS_TIMING_VALUE ; + } + + rlpw = DBI_CYCLES(timing->rlpw); + if (rlpw > MAX_DBI_RWLPW_TIMING_VALUE) { + rlpw = MAX_DBI_RWLPW_TIMING_VALUE ; + } + + rhpw = DBI_CYCLES (timing->rhpw); + if (rhpw > MAX_DBI_RWHPW_TIMING_VALUE) { + rhpw = MAX_DBI_RWHPW_TIMING_VALUE ; + } + + wcss = DBI_CYCLES(timing->wcss); + if (wcss > MAX_DBI_RWCSS_TIMING_VALUE) { + wcss = MAX_DBI_RWCSS_TIMING_VALUE ; + } + + wlpw = DBI_CYCLES(timing->wlpw); + if (wlpw > MAX_DBI_RWLPW_TIMING_VALUE) { + wlpw = MAX_DBI_RWLPW_TIMING_VALUE ; + } + +#ifndef CONFIG_LCD_CS_ALWAYS_LOW + /* dispc/lcdc will waste one cycle because CS pulse will use one cycle*/ + whpw = DBI_CYCLES (timing->whpw) - 1; +#else + whpw = DBI_CYCLES (timing->whpw) ; +#endif + if (whpw > MAX_DBI_RWHPW_TIMING_VALUE) { + whpw = MAX_DBI_RWHPW_TIMING_VALUE ; + } + + return (whpw | (wlpw << 6) | (wcss << 12) + | (rhpw << 16) |(rlpw << 22) | (rcss << 28)); +} + +#ifdef CONFIG_FB_LCD_CS1 +/*cs1*/ +static void mcu_dispc_init_config(struct panel_spec *panel) +{ + uint32_t reg_val = 0; + + pr_debug("autotst_dispc: [%s] for cs1\n", __FUNCTION__); + + if(NULL == panel){ + printk(KERN_ERR "autotst_dispc: [%s] fail.(Invalid Param)\n", __FUNCTION__); + return; + } + + if(SPRDFB_PANEL_TYPE_MCU != panel->type){ + printk(KERN_ERR "autotst_dispc: [%s] fail.(not mcu panel)\n", __FUNCTION__); + return; + } + + /*use dbi as interface*/ + dispc_set_bits((2<<1), DISPC_CTRL); + autotst_dispc_ctx.dispc_if = DISPC_IF_DBI; + + /* CS1 bus mode [BIT8]: 8080/6800 */ + switch (panel->info.mcu->bus_mode) { + case LCD_BUS_8080: + break; + case LCD_BUS_6800: + reg_val |= (1<<8); + break; + default: + break; + } + /* CS1 bus width [BIT11:9] */ + switch (panel->info.mcu->bus_width) { + case 8: + break; + case 9: + reg_val |= (1 << 9); + break; + case 16: + reg_val |= (2 << 9); + break; + case 18: + reg_val |= (3 << 9) ; + break; + case 24: + reg_val |= (4 << 9); + break; + default: + break; + } + + /*CS1 pixel bits [BIT13:12]*/ + switch (panel->info.mcu->bpp) { + case 16: + break; + case 18: + reg_val |= (1 << 12) ; + break; + case 24: + reg_val |= (2 << 12); + break; + default: + break; + } + +#ifndef CONFIG_FB_NO_FMARK + /*TE enable*/ + reg_val |= (1 << 16); + if(SPRDFB_POLARITY_NEG == panel->info.mcu->te_pol){ + reg_val |= (1<< 17); + } + dispc_write(panel->info.mcu->te_sync_delay, DISPC_TE_SYNC_DELAY); +#endif + +#ifdef CONFIG_LCD_CS_ALWAYS_LOW + /*CS alway low mode*/ + reg_val |= (1<<21); +#else + /*CS not alway low mode*/ +#endif + + /*CS1 selected*/ + reg_val |= (1 << 20); + + dispc_write(reg_val, DISPC_DBI_CTRL); + + pr_debug("autotst_dispc: [%s] DISPC_DBI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DBI_CTRL)); +} + +static void mcu_dispc_set_timing(struct panel_spec *panel) +{ + uint32_t timing = 0; + + pr_debug("autotst_dispc: [%s] for cs1\n", __FUNCTION__); + + timing = mcu_calc_timing(panel->info.mcu->timing); + dispc_write(timing,DISPC_DBI_TIMING1); +} + +#else +/*cs0*/ +static void mcu_dispc_init_config(struct panel_spec *panel) +{ + uint32_t reg_val = 0; + + pr_debug("autotst_dispc: [%s] for cs0\n", __FUNCTION__); + + if(NULL == panel){ + printk(KERN_ERR "autotst_dispc: [%s] fail.(Invalid Param)\n", __FUNCTION__); + return; + } + + if(SPRDFB_PANEL_TYPE_MCU != panel->type){ + printk(KERN_ERR "autotst_dispc: [%s] fail.(not mcu panel)\n", __FUNCTION__); + return; + } + + /*use dbi as interface*/ + dispc_set_bits((2<<1), DISPC_CTRL); + autotst_dispc_ctx.dispc_if = DISPC_IF_DBI; + + /* CS0 bus mode [BIT0]: 8080/6800 */ + switch (panel->info.mcu->bus_mode) { + case LCD_BUS_8080: + break; + case LCD_BUS_6800: + reg_val |= 1; + break; + default: + break; + } + /* CS0 bus width [BIT3:1] */ + switch (panel->info.mcu->bus_width) { + case 8: + break; + case 9: + reg_val |= (1 << 1); + break; + case 16: + reg_val |= (2 << 1); + break; + case 18: + reg_val |= (3 << 1) ; + break; + case 24: + reg_val |= (4 << 1); + break; + default: + break; + } + + /*CS0 pixel bits [BIT5:4]*/ + switch (panel->info.mcu->bpp) { + case 16: + break; + case 18: + reg_val |= (1 << 4) ; + break; + case 24: + reg_val |= (2 << 4); + break; + default: + break; + } + +#ifndef CONFIG_FB_NO_FMARK + /*TE enable*/ + reg_val |= (1 << 16); + if(SPRDFB_POLARITY_NEG == panel->info.mcu->te_pol){ + reg_val |= (1<< 17); + } + dispc_write(panel->info.mcu->te_sync_delay, DISPC_TE_SYNC_DELAY); +#endif + +#ifdef CONFIG_LCD_CS_ALWAYS_LOW + /*CS alway low mode*/ + reg_val |= (1<<21); +#else + /*CS not alway low mode*/ +#endif + + /*CS0 selected*/ + + dispc_write(reg_val, DISPC_DBI_CTRL); + + pr_debug("autotst_dispc: [%s] DISPC_DBI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DBI_CTRL)); +} + +static void mcu_dispc_set_timing(struct panel_spec *panel) +{ + uint32_t timing = 0; + + pr_debug("autotst_dispc: [%s] for cs0\n", __FUNCTION__); + + timing = mcu_calc_timing(panel->info.mcu->timing); + dispc_write(timing,DISPC_DBI_TIMING0); +} +#endif + + +/**********************************************/ +/* RGB PANEL CONFIG */ +/**********************************************/ +static uint32_t rgb_calc_h_timing(struct timing_rgb *timing) +{ + return (timing->hsync | (timing->hbp << 8) | (timing->hfp << 20)); +} + + +static uint32_t rgb_calc_v_timing(struct timing_rgb *timing) +{ + return (timing->vsync| (timing->vbp << 8) | (timing->vfp << 20)); +} + +static void rgb_dispc_init_config(struct panel_spec *panel) +{ + uint32_t reg_val = dispc_read(DISPC_DPI_CTRL); + + pr_debug("autotst_dispc: [%s]\n", __FUNCTION__); + + if(NULL == panel){ + printk(KERN_ERR "autotst_dispc: [%s] fail.(Invalid Param)\n", __FUNCTION__); + return; + } + + if(SPRDFB_PANEL_TYPE_RGB != panel->type){ + printk(KERN_ERR "autotst_dispc: [%s] fail.(not mcu panel)\n", __FUNCTION__); + return; + } + + /*use dpi as interface*/ + dispc_clear_bits((3<<1), DISPC_CTRL); + autotst_dispc_ctx.dispc_if = DISPC_IF_DPI; + + /*h sync pol*/ + if(SPRDFB_POLARITY_NEG == panel->info.rgb->h_sync_pol){ + reg_val |= (1<<0); + } + + /*v sync pol*/ + if(SPRDFB_POLARITY_NEG == panel->info.rgb->v_sync_pol){ + reg_val |= (1<<1); + } + + /*de sync pol*/ + if(SPRDFB_POLARITY_NEG == panel->info.rgb->de_pol){ + reg_val |= (1<<2); + } + +#ifdef CONFIG_DPI_SINGLE_RUN + /*single run mode*/ + reg_val |= (1<<3); +#endif + + /*dpi bits*/ + switch(panel->info.rgb->video_bus_width){ + case 16: + break; + case 18: + reg_val |= (1 << 6); + break; + case 24: + reg_val |= (2 << 6); + break; + default: + break; + } + + dispc_write(reg_val, DISPC_DPI_CTRL); + + pr_debug("autotst_dispc: [%s] DISPC_DPI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DPI_CTRL)); +} + +static void rgb_dispc_set_timing(struct panel_spec *panel) +{ + uint32_t timing_h = 0; + uint32_t timing_v = 0; + + pr_debug("autotst_dispc: [%s]\n", __FUNCTION__); + + timing_h = rgb_calc_h_timing(panel->info.rgb->timing); + timing_v = rgb_calc_v_timing(panel->info.rgb->timing); + + dispc_write(timing_h, DISPC_DPI_H_TIMING); + dispc_write(timing_v, DISPC_DPI_V_TIMING); +} + + +/**********************************************/ +/* MIPI PANEL CONFIG */ +/**********************************************/ +static void mipi_dispc_init_config(struct panel_spec *panel) +{ + uint32_t reg_val = dispc_read(DISPC_DPI_CTRL); + + pr_debug("autotst_dispc: [%s]\n", __FUNCTION__); + + if(NULL == panel){ + printk(KERN_ERR "autotst_dispc: [%s] fail.(Invalid Param)\n", __FUNCTION__); + return; + } + + if(SPRDFB_PANEL_TYPE_MIPI != panel->type){ + printk(KERN_ERR "autotst_dispc: [%s] fail.(not mcu panel)\n", __FUNCTION__); + return; + } + + if(SPRDFB_MIPI_MODE_CMD == panel->info.mipi->work_mode){ + /*use edpi as interface*/ + dispc_set_bits((1<<1), DISPC_CTRL); + autotst_dispc_ctx.dispc_if = DISPC_IF_EDPI; + }else{ + /*use dpi as interface*/ + dispc_clear_bits((3<<1), DISPC_CTRL); + autotst_dispc_ctx.dispc_if = DISPC_IF_DPI; + } + + /*h sync pol*/ + if(SPRDFB_POLARITY_NEG == panel->info.mipi->h_sync_pol){ + reg_val |= (1<<0); + } + + /*v sync pol*/ + if(SPRDFB_POLARITY_NEG == panel->info.mipi->v_sync_pol){ + reg_val |= (1<<1); + } + + /*de sync pol*/ + if(SPRDFB_POLARITY_NEG == panel->info.mipi->de_pol){ + reg_val |= (1<<2); + } + + if(SPRDFB_MIPI_MODE_VIDEO == panel->info.mipi->work_mode){ +#ifdef CONFIG_DPI_SINGLE_RUN + /*single run mode*/ + reg_val |= (1<<3); +#endif + }else{ + if(!(panel->cap & PANEL_CAP_NOT_TEAR_SYNC)){ + printk("autotst_dispc: mipi_dispc_init_config not support TE\n"); + /*enable te*/ + reg_val |= (1<<8); + } + /*te pol*/ + if(SPRDFB_POLARITY_NEG == panel->info.mipi->te_pol){ + reg_val |= (1<<9); + } + /*use external te*/ + reg_val |= (1<<10); + } + + /*dpi bits*/ + switch(panel->info.rgb->video_bus_width){ + case 16: + break; + case 18: + reg_val |= (1 << 6); + break; + case 24: + reg_val |= (2 << 6); + break; + default: + break; + } + + dispc_write(reg_val, DISPC_DPI_CTRL); + + pr_debug("autotst_dispc: [%s] DISPC_DPI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DPI_CTRL)); +} + +static void mipi_dispc_set_timing(struct panel_spec *panel) +{ + uint32_t timing_h = 0; + uint32_t timing_v = 0; + + pr_debug("autotst_dispc: [%s]\n", __FUNCTION__); + + timing_h = rgb_calc_h_timing(panel->info.mipi->timing); + timing_v = rgb_calc_v_timing(panel->info.mipi->timing); + + dispc_write(timing_h, DISPC_DPI_H_TIMING); + dispc_write(timing_v, DISPC_DPI_V_TIMING); +} + +/**********************************************/ +/* COMMON CONFIG */ +/**********************************************/ +static void dispc_print_clk(void) +{ + uint32_t reg_val0,reg_val1,reg_val2; + reg_val0 = sci_glb_read(SPRD_AONAPB_BASE+0x4, 0xffffffff); + reg_val1 = sci_glb_read(SPRD_AHB_BASE, 0xffffffff); + reg_val2 = sci_glb_read(SPRD_APBREG_BASE, 0xffffffff); + printk("autotst_dispc:0x402e0004 = 0x%x 0x20d00000 = 0x%x 0x71300000 = 0x%x \n",reg_val0, reg_val1, reg_val2); + reg_val0 = sci_glb_read(SPRD_APBCKG_BASE+0x34, 0xffffffff); + reg_val1 = sci_glb_read(SPRD_APBCKG_BASE+0x30, 0xffffffff); + reg_val2 = sci_glb_read(SPRD_APBCKG_BASE+0x2c, 0xffffffff); + printk("autotst_dispc:0x71200034 = 0x%x 0x71200030 = 0x%x 0x7120002c = 0x%x \n",reg_val0, reg_val1, reg_val2); +} + +static void dispc_reset(void) +{ + sci_glb_set(REG_AHB_SOFT_RST, (BIT_DISPC0_SOFT_RST) ); + udelay(10); + sci_glb_clr(REG_AHB_SOFT_RST, (BIT_DISPC0_SOFT_RST) ); +} + +static inline void dispc_set_bg_color(uint32_t bg_color) +{ + dispc_write(bg_color, DISPC_BG_COLOR); +} + +static inline void dispc_set_osd_ck(uint32_t ck_color) +{ + dispc_write(ck_color, DISPC_OSD_CK); +} + +static inline void dispc_osd_enable(bool is_enable) +{ + uint32_t reg_val; + + reg_val = dispc_read(DISPC_OSD_CTRL); + if(is_enable){ + reg_val = reg_val | (BIT(0)); + } + else{ + reg_val = reg_val & (~(BIT(0))); + } + dispc_write(reg_val, DISPC_OSD_CTRL); +} + + +static void dispc_dithering_enable(bool enable) +{ + if(enable){ + dispc_set_bits(BIT(6), DISPC_CTRL); + }else{ + dispc_clear_bits(BIT(6), DISPC_CTRL); + } +} + +static void dispc_pwr_enable(bool enable) +{ + if(enable){ + dispc_set_bits(BIT(7), DISPC_CTRL); + }else{ + dispc_clear_bits(BIT(7), DISPC_CTRL); + } +} + +static void dispc_set_exp_mode(uint16_t exp_mode) +{ + uint32_t reg_val = dispc_read(DISPC_CTRL); + + reg_val &= ~(0x3 << 16); + reg_val |= (exp_mode << 16); + dispc_write(reg_val, DISPC_CTRL); +} + +static void dispc_module_enable(void) +{ + /*dispc module enable */ + dispc_write((1<<0), DISPC_CTRL); + + /*disable dispc INT*/ + dispc_write(0x0, DISPC_INT_EN); + + /* clear dispc INT */ + dispc_write(0x1F, DISPC_INT_CLR); +} + +static void dispc_layer_init(struct panel_spec *panel) +{ + uint32_t reg_val = 0; + +// dispc_clear_bits((1<<0),DISPC_IMG_CTRL); + dispc_write(0x0, DISPC_IMG_CTRL); + dispc_clear_bits((1<<0),DISPC_OSD_CTRL); + + /******************* OSD layer setting **********************/ + + /*enable OSD layer*/ + reg_val |= (1 << 0); + + /*disable color key */ + + /* alpha mode select - block alpha*/ + reg_val |= (1 << 2); + + /* data format */ + //if (var->bits_per_pixel == 32) { + if(1){ + /* ABGR */ + reg_val |= (3 << 4); + /* rb switch */ + reg_val |= (1 << 15); + } else { + /* RGB565 */ + reg_val |= (5 << 4); + /* B2B3B0B1 */ + reg_val |= (2 << 8); + } + + dispc_write(reg_val, DISPC_OSD_CTRL); + + /* OSD layer alpha value */ + dispc_write(0xff, DISPC_OSD_ALPHA); + + /* OSD layer size */ + reg_val = ( panel->width & 0xfff) | (( panel->height & 0xfff ) << 16); + dispc_write(reg_val, DISPC_OSD_SIZE_XY); + + /* OSD layer start position */ + dispc_write(0, DISPC_OSD_DISP_XY); + + /* OSD layer pitch */ + reg_val = ( panel->width & 0xfff) ; + dispc_write(reg_val, DISPC_OSD_PITCH); + + /* OSD color_key value */ + dispc_set_osd_ck(0x0); + + /* DISPC workplane size */ + reg_val = ( panel->width & 0xfff) | ((panel->height & 0xfff ) << 16); + dispc_write(reg_val, DISPC_SIZE_XY); +} + +static void dispc_run(void) +{ + if(DISPC_IF_DPI == autotst_dispc_ctx.dispc_if){ + /*dpi register update*/ + dispc_set_bits(BIT(5), DISPC_DPI_CTRL); + udelay(30); + + /*dpi register update with SW and VSync*/ + dispc_clear_bits(BIT(4), DISPC_DPI_CTRL); + + /* start refresh */ + dispc_set_bits((1 << 4), DISPC_CTRL); + + }else{ + /* start refresh */ + dispc_set_bits((1 << 4), DISPC_CTRL); + } +} + +static void dispc_stop(void) +{ + if(DISPC_IF_DPI == autotst_dispc_ctx.dispc_if){ + /*dpi register update with SW only*/ + dispc_set_bits(BIT(4), DISPC_DPI_CTRL); + + /* stop refresh */ + dispc_clear_bits((1 << 4), DISPC_CTRL); + } +} + +static int dispc_clk_enable(struct autotst_dispc_context *dispc_ctx_ptr) +{ + int ret = 0; + bool is_dispc_enable=false; + bool is_dispc_dpi_enable=false; + + pr_debug(KERN_INFO "autotst_dispc:[%s]\n",__FUNCTION__); + if(!dispc_ctx_ptr){ + return -1; + } + + ret = clk_enable(dispc_ctx_ptr->clk_dispc); + if(ret){ + printk("autotst_dispc:enable clk_dispc error!!!\n"); + ret=-1; + goto ERROR_CLK_ENABLE; + } + is_dispc_enable=true; + ret = clk_enable(dispc_ctx_ptr->clk_dispc_dpi); + if(ret){ + printk("autotst_dispc:enable clk_dispc_dpi error!!!\n"); + ret=-1; + goto ERROR_CLK_ENABLE; + } + is_dispc_dpi_enable=true; + ret = clk_enable(dispc_ctx_ptr->clk_dispc_dbi); + if(ret){ + printk("autotst_dispc:enable clk_dispc_dbi error!!!\n"); + ret=-1; + goto ERROR_CLK_ENABLE; + } + + return ret; + +ERROR_CLK_ENABLE: + if(is_dispc_enable){ + clk_disable(dispc_ctx_ptr->clk_dispc); + } + if(is_dispc_dpi_enable){ + clk_disable(dispc_ctx_ptr->clk_dispc_dpi); + } + + printk("autotst_dispc:sprdfb_dispc_clk_enable error!!!!!!\n"); + return ret; +} + +static int32_t dispc_clk_init(void) +{ + int ret = 0; + struct clk *clk_parent1, *clk_parent2, *clk_parent3, *clk_parent4; + + pr_debug(KERN_INFO "autotst_dispc:[%s]\n", __FUNCTION__); + + sci_glb_set(DISPC_CORE_EN, BIT_DISPC_CORE_EN); + + clk_parent1 = clk_get(NULL, DISPC_CLOCK_PARENT); + if (IS_ERR(clk_parent1)) { + printk(KERN_WARNING "autotst_dispc: get clk_parent1 fail!\n"); + return -1; + } else { + pr_debug(KERN_INFO "autotst_dispc: get clk_parent1 ok!\n"); + } + + clk_parent2 = clk_get(NULL, DISPC_DBI_CLOCK_PARENT); + if (IS_ERR(clk_parent2)) { + printk(KERN_WARNING "autotst_dispc: get clk_parent2 fail!\n"); + return -1; + } else { + pr_debug(KERN_INFO "autotst_dispc: get clk_parent2 ok!\n"); + } + + clk_parent3 = clk_get(NULL, DISPC_DPI_CLOCK_PARENT); + if (IS_ERR(clk_parent3)) { + printk(KERN_WARNING "autotst_dispc: get clk_parent3 fail!\n"); + return -1; + } else { + pr_debug(KERN_INFO "autotst_dispc: get clk_parent3 ok!\n"); + } + + clk_parent4 = clk_get(NULL, DISPC_EMC_EN_PARENT); + if (IS_ERR(clk_parent3)) { + printk(KERN_WARNING "autotst_dispc: get clk_parent4 fail!\n"); + return -1; + } else { + pr_debug(KERN_INFO "autotst_dispc: get clk_parent4 ok!\n"); + } + + autotst_dispc_ctx.clk_dispc = clk_get(NULL, DISPC_PLL_CLK); + if (IS_ERR(autotst_dispc_ctx.clk_dispc)) { + printk(KERN_WARNING "autotst_dispc: get clk_dispc fail!\n"); + return -1; + } else { + pr_debug(KERN_INFO "autotst_dispc: get clk_dispc ok!\n"); + } + + autotst_dispc_ctx.clk_dispc_dbi = clk_get(NULL, DISPC_DBI_CLK); + if (IS_ERR(autotst_dispc_ctx.clk_dispc_dbi)) { + printk(KERN_WARNING "autotst_dispc: get clk_dispc_dbi fail!\n"); + return -1; + } else { + pr_debug(KERN_INFO "autotst_dispc: get clk_dispc_dbi ok!\n"); + } + + autotst_dispc_ctx.clk_dispc_dpi = clk_get(NULL, DISPC_DPI_CLK); + if (IS_ERR(autotst_dispc_ctx.clk_dispc_dpi)) { + printk(KERN_WARNING "autotst_dispc: get clk_dispc_dpi fail!\n"); + return -1; + } else { + pr_debug(KERN_INFO "autotst_dispc: get clk_dispc_dpi ok!\n"); + } + + autotst_dispc_ctx.clk_dispc_emc = clk_get(NULL, DISPC_EMC_CLK); + if (IS_ERR(autotst_dispc_ctx.clk_dispc_emc)) { + printk(KERN_WARNING "autotst_dispc: get clk_dispc_dpi fail!\n"); + return -1; + } else { + pr_debug(KERN_INFO "autotst_dispc: get clk_dispc_emc ok!\n"); + } + + ret = clk_set_parent(autotst_dispc_ctx.clk_dispc, clk_parent1); + if(ret){ + printk(KERN_ERR "autotst_dispc: dispc set clk parent fail\n"); + } + ret = clk_set_rate(autotst_dispc_ctx.clk_dispc, DISPC_CLOCK); + if(ret){ + printk(KERN_ERR "autotst_dispc: dispc set clk parent fail\n"); + } + + ret = clk_set_parent(autotst_dispc_ctx.clk_dispc_dbi, clk_parent2); + if(ret){ + printk(KERN_ERR "autotst_dispc: dispc set dbi clk parent fail\n"); + } + ret = clk_set_rate(autotst_dispc_ctx.clk_dispc_dbi, DISPC_DBI_CLOCK); + if(ret){ + printk(KERN_ERR "autotst_dispc: dispc set dbi clk parent fail\n"); + } + + ret = clk_set_parent(autotst_dispc_ctx.clk_dispc_dpi, clk_parent3); + if(ret){ + printk(KERN_ERR "autotst_dispc: dispc set dpi clk parent fail\n"); + } + ret = clk_set_rate(autotst_dispc_ctx.clk_dispc_dpi, DISPC_DPI_CLOCK); + if(ret){ + printk(KERN_ERR "autotst_dispc: dispc set dpi clk parent fail\n"); + } + + ret = clk_set_parent(autotst_dispc_ctx.clk_dispc_emc, clk_parent4); + if(ret){ + printk(KERN_ERR "autotst_dispc: dispc set emc clk parent fail\n"); + } + + ret = clk_enable(autotst_dispc_ctx.clk_dispc_emc); + if(ret){ + printk("autotst_dispc:enable clk_dispc_emc error!!!\n"); + return -1; + } + + ret = dispc_clk_enable(&autotst_dispc_ctx); + if (ret) { + printk(KERN_WARNING "autotst_dispc:[%s] enable dispc_clk fail!\n",__FUNCTION__); + return -1; + } else { + pr_debug(KERN_INFO "autotst_dispc:[%s] enable dispc_clk ok!\n",__FUNCTION__); + } + + dispc_print_clk(); + + return 0; +} + +static int dispc_clk_disable(struct autotst_dispc_context *dispc_ctx_ptr) +{ + pr_debug(KERN_INFO "autotst_dispc:[%s]\n",__FUNCTION__); + if(!dispc_ctx_ptr){ + return 0; + } + + pr_debug(KERN_INFO "autotst_dispc:sprdfb_dispc_clk_disable real\n"); + clk_disable(dispc_ctx_ptr->clk_dispc); + clk_disable(dispc_ctx_ptr->clk_dispc_dpi); + clk_disable(dispc_ctx_ptr->clk_dispc_dbi); + + return 0; +} + +static void draw_patten(uint32_t* buffer, int buffer_w, int buffer_h, int grid_w, int grid_h) +{ + int h = 0; + int v = 0; + int i,j; + int grid_in_width = buffer_h / grid_w; + unsigned int c = 0; + + for (j = 0; j < buffer_h; j++) { + for (i = 0; i < buffer_w; i++) { + h = i / grid_w; + v = j / grid_h; + c = g_patten_table[(v*grid_in_width+h) % PATTEN_COLOR_COUNT]; + buffer[j*buffer_w+i] = c; + } + } +} + +static int dispc_fb_prepare(struct panel_spec *panel) +{ + uint32_t fb_size = 0;// should be ABGR888 + uint32_t *p_pixel = NULL; + + fb_size = panel->width * panel->height * 4;// should be ABGR888 + + autotst_dispc_ctx.fb_addr_v = __get_free_pages(GFP_ATOMIC | __GFP_ZERO , get_order(fb_size)); + if (!autotst_dispc_ctx.fb_addr_v) { + printk(KERN_ERR "sprdfb: %s Failed to allocate frame buffer\n", __FUNCTION__); + return -1; + } + printk(KERN_INFO "sprdfb: got %d bytes frame buffer at 0x%x\n", fb_size, + autotst_dispc_ctx.fb_addr_v); + + autotst_dispc_ctx.fb_addr_p = __pa(autotst_dispc_ctx.fb_addr_v); + autotst_dispc_ctx.fb_size = fb_size; + + p_pixel = autotst_dispc_ctx.fb_addr_v; + draw_patten(p_pixel, panel->width, panel->height, PATTEN_GRID_WIDTH, PATTEN_GRID_HEIGHT); + + return 0; +} + +void dispc_dump(void) +{ + int i = 0; + for(i=0;i<256;i+=16){ + printk("autotst_dispc: %x: 0x%x, 0x%x, 0x%x, 0x%x\n", i, dispc_read(i), + dispc_read(i+4), + dispc_read(i+8), + dispc_read(i+12)); + } + printk("**************************\n"); +} + +int32_t autotst_dispc_uninit(int display_type) +{ + printk(KERN_INFO "autotst_dispc:[%s]\n",__FUNCTION__); + + dispc_stop(); + dispc_clk_disable(&autotst_dispc_ctx); + if(DISPLAY_TYPE_MIPI == display_type){ + autotst_dsi_uninit(); + } + if(0 != autotst_dispc_ctx.fb_addr_v){ + free_pages(autotst_dispc_ctx.fb_addr_v, get_order(autotst_dispc_ctx.fb_size)); + } + autotst_dispc_ctx.fb_addr_v = 0; + autotst_dispc_ctx.fb_addr_p = 0; + autotst_dispc_ctx.fb_size = 0; + return 0; +} + +int32_t autotst_dispc_init(int display_type) +{ + int ret = 0; + + printk(KERN_INFO "autotst_dispc:[%s]\n",__FUNCTION__); + + //autotst_dsi_dump(); + + autotst_dispc_uninit(DISPLAY_TYPE_MIPI); + + ret = dispc_clk_init(); + if(ret){ + printk(KERN_WARNING "autotst_dispc: dispc_clk_init fail!\n"); + return -1; + } + + dispc_reset(); + dispc_module_enable(); + + /*set bg color*/ + dispc_set_bg_color(0xFFFFFFFF); + /*enable dithering*/ + dispc_dithering_enable(true); + /*use MSBs as img exp mode*/ + dispc_set_exp_mode(0x0); + //enable DISPC Power Control + dispc_pwr_enable(true); + + switch(display_type){ + case DISPLAY_TYPE_MCU: + autotst_panel = &lcd_dummy_mcu_spec; + mcu_dispc_init_config(autotst_panel); + mcu_dispc_set_timing(autotst_panel); + break; + case DISPLAY_TYPE_RGB: + autotst_panel = &lcd_dummy_rgb_spec; + rgb_dispc_init_config(autotst_panel); + rgb_dispc_set_timing(autotst_panel); + autotst_dispc_ctx.dispc_if = DISPC_IF_DPI; + break; + case DISPLAY_TYPE_MIPI: + autotst_panel = &lcd_dummy_mipi_spec; + mipi_dispc_init_config(autotst_panel); + mipi_dispc_set_timing(autotst_panel); + autotst_dsi_init(autotst_panel); + break; + default: + printk("autotst_dispc:[%s] error display type (%d)\n", __FUNCTION__, display_type); + } + + dispc_layer_init(autotst_panel); + + if(DISPC_IF_DPI == autotst_dispc_ctx.dispc_if){ + if(1){ + /*set dpi register update only with SW*/ + dispc_set_bits(BIT(4), DISPC_DPI_CTRL); + }else{ + /*set dpi register update with SW & VSYNC*/ + dispc_clear_bits(BIT(4), DISPC_DPI_CTRL); + } + /*enable dispc update done INT*/ + //dispc_write((1<<4), DISPC_INT_EN); + }else{ + /* enable dispc DONE INT*/ + //dispc_write((1<<0), DISPC_INT_EN); + } + //dispc_set_bits(BIT(2), DISPC_INT_EN); + return 0; +} + +int32_t autotst_dispc_refresh (void) +{ + int ret = 0; + uint32_t size = (autotst_panel->width& 0xffff) | ((autotst_panel->height) << 16); + printk(KERN_INFO "autotst_dispc:[%s]\n",__FUNCTION__); + + //autotst_dsi_dump(); + + ret = dispc_fb_prepare(autotst_panel); + if(0 != ret){ + printk("autotst_dispc: refresh fail!(can't prepare frame buffer)!]n"); + return -1; + } + + dispc_write(autotst_dispc_ctx.fb_addr_p, DISPC_OSD_BASE_ADDR); + dispc_write(0, DISPC_OSD_DISP_XY); + dispc_write(size, DISPC_OSD_SIZE_XY); + dispc_write(autotst_panel->width, DISPC_OSD_PITCH); + dispc_write(size, DISPC_SIZE_XY); + + dispc_run(); + +#if 1 + pr_debug("DISPC_CTRL: 0x%x\n", dispc_read(DISPC_CTRL)); + pr_debug("DISPC_SIZE_XY: 0x%x\n", dispc_read(DISPC_SIZE_XY)); + pr_debug("DISPC_BG_COLOR: 0x%x\n", dispc_read(DISPC_BG_COLOR)); + pr_debug("DISPC_INT_EN: 0x%x\n", dispc_read(DISPC_INT_EN)); + pr_debug("DISPC_OSD_CTRL: 0x%x\n", dispc_read(DISPC_OSD_CTRL)); + pr_debug("DISPC_OSD_BASE_ADDR: 0x%x\n", dispc_read(DISPC_OSD_BASE_ADDR)); + pr_debug("DISPC_OSD_SIZE_XY: 0x%x\n", dispc_read(DISPC_OSD_SIZE_XY)); + pr_debug("DISPC_OSD_PITCH: 0x%x\n", dispc_read(DISPC_OSD_PITCH)); + pr_debug("DISPC_OSD_DISP_XY: 0x%x\n", dispc_read(DISPC_OSD_DISP_XY)); + pr_debug("DISPC_OSD_ALPHA : 0x%x\n", dispc_read(DISPC_OSD_ALPHA)); +#else + mdelay(20); + dispc_dump(); + autotst_dsi_dump(); + autotst_dsi_dump1(); +#endif + return 0; +} + +/**********************************************/ +/* MCU OPERATION */ +/**********************************************/ +int32_t autotst_dispc_mcu_send_cmd(uint32_t cmd) +{ + /* busy wait for ahb fifo full sign's disappearance */ + while(dispc_read(DISPC_DBI_QUEUE) & BIT(5)); + + dispc_write(cmd, DISPC_DBI_CMD); + + return 0; +} + +int32_t autotst_dispc_mcu_send_cmd_data(uint32_t cmd, uint32_t data) +{ + /* busy wait for ahb fifo full sign's disappearance */ + while(dispc_read(DISPC_DBI_QUEUE) & BIT(5)); + + dispc_write(cmd, DISPC_DBI_CMD); + + /* busy wait for ahb fifo full sign's disappearance */ + while(dispc_read(DISPC_DBI_QUEUE) & BIT(5)); + + dispc_write(data, DISPC_DBI_DATA); + + return 0; +} + +int32_t autotst_dispc_mcu_send_data(uint32_t data) +{ + /* busy wait for ahb fifo full sign's disappearance */ + while(dispc_read(DISPC_DBI_QUEUE) & BIT(5)); + + dispc_write(data, DISPC_DBI_DATA); + + return 0; +} + +uint32_t autotst_dispc_mcu_read_data(void) +{ + /* busy wait for ahb fifo full sign's disappearance */ + while(dispc_read(DISPC_DBI_QUEUE) & BIT(5)); + dispc_write(1 << 24, DISPC_DBI_DATA); + udelay(50); + return dispc_read(DISPC_DBI_RDATA); +} + + diff --git a/drivers/autotst/dispc.h b/drivers/autotst/dispc.h new file mode 100644 index 00000000..98844358 --- /dev/null +++ b/drivers/autotst/dispc.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 _DISPC_H_ +#define _DISPC_H_ + +typedef enum{ + DISPLAY_TYPE_MCU = 0, + DISPLAY_TYPE_RGB, + DISPLAY_TYPE_MIPI, +}E_DISPLAY_TYPE; + +enum DISPC_PIN_FUNC { + DISPC_PIN_FUNC0 = 0, + DISPC_PIN_FUNC1, + DISPC_PIN_FUNC2, + DISPC_PIN_FUNC3, +}; + +int32_t autotst_dispc_mcu_send_cmd(uint32_t cmd); +int32_t autotst_dispc_mcu_send_cmd_data(uint32_t cmd, uint32_t data); +int32_t autotst_dispc_mcu_send_data(uint32_t data); +uint32_t autotst_dispc_mcu_read_data(void); + +int32_t autotst_dispc_init(int display_type); +int32_t autotst_dispc_uninit(int display_type); +int32_t autotst_dispc_refresh (void); +int autotst_pin_ctrl(int type, int gpio_num, int gpio_pull); + +//int autotst_dispc_pin_ctrl(int type); + +#endif diff --git a/drivers/autotst/dispc_reg.h b/drivers/autotst/dispc_reg.h new file mode 100644 index 00000000..869c47da --- /dev/null +++ b/drivers/autotst/dispc_reg.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 _DISPC_REG_H_ +#define _DISPC_REG_H_ + +#include +#include +#include +#include + +/* DISPC regs offset */ +#define DISPC_CTRL (0x0000) +#define DISPC_SIZE_XY (0x0004) +#define DISPC_RSTN (0x0008) + +#define DISPC_STS (0x0010) + +#define DISPC_IMG_CTRL (0x0020) +#define DISPC_IMG_Y_BASE_ADDR (0x0024) +#define DISPC_IMG_UV_BASE_ADDR (0x0028) +#define DISPC_IMG_V_BASE_ADDR (0x002c) +#define DISPC_IMG_SIZE_XY (0x0030) +#define DISPC_IMG_PITCH (0x0034) +#define DISPC_IMG_DISP_XY (0x0038) +#define DISPC_BG_COLOR (0x003c) + +#define DISPC_OSD_CTRL (0x0040) +#define DISPC_OSD_BASE_ADDR (0x0044) +#define DISPC_OSD_SIZE_XY (0x0048) +#define DISPC_OSD_PITCH (0x004c) +#define DISPC_OSD_DISP_XY (0x0050) +#define DISPC_OSD_ALPHA (0x0054) +#define DISPC_OSD_CK (0x0058) + +#define DISPC_Y2R_CTRL (0x0060) +#define DISPC_Y2R_CONTRAST (0x0064) +#define DISPC_Y2R_SATURATION (0x0068) +#define DISPC_Y2R_BRIGHTNESS (0x006c) + +#define DISPC_INT_EN (0x0070) +#define DISPC_INT_CLR (0x0074) +#define DISPC_INT_STATUS (0x0078) +#define DISPC_INT_RAW (0x007c) + +#define DISPC_DPI_CTRL (0x0080) +#define DISPC_DPI_H_TIMING (0x0084) +#define DISPC_DPI_V_TIMING (0x0088) +#define DISPC_DPI_STS0 (0x008c) +#define DISPC_DPI_STS1 (0x0090) + +#define DISPC_DBI_CTRL (0x00a0) +#define DISPC_DBI_TIMING0 (0x00a4) +#define DISPC_DBI_TIMING1 (0x00a8) +#define DISPC_DBI_RDATA (0x00ac) +#define DISPC_DBI_CMD (0x00b0) +#define DISPC_DBI_DATA (0x00b4) +#define DISPC_DBI_QUEUE (0x00b8) + + + +//shadow register , read only +#define SHDW_IMG_CTRL (0x00C0) +#define SHDW_IMG_Y_BASE_ADDR (0x00C4) +#define SHDW_IMG_UV_BASE_ADDR (0x00C8) +#define SHDW_IMG_V_BASE_ADDR (0x00CC) +#define SHDW_IMG_SIZE_XY (0x00D0) +#define SHDW_IMG_PITCH (0x00D4) +#define SHDW_IMG_DISP_XY (0x00D8) +#define SHDW_BG_COLOR (0x00DC) +#define SHDW_OSD_CTRL (0x00E0) +#define SHDW_OSD_BASE_ADDR (0x00E4) +#define SHDW_OSD_SIZE_XY (0x00E8) +#define SHDW_OSD_PITCH (0x00EC) +#define SHDW_OSD_DISP_XY (0x00F0) +#define SHDW_OSD_ALPHA (0x00F4) +#define SHDW_OSD_CK (0x00F8) +#define SHDW_Y2R_CTRL (0x0100) +#define SHDW_Y2R_CONTRAST (0x0104) +#define SHDW_Y2R_SATURATION (0x0108) +#define SHDW_Y2R_BRIGHTNESS (0x010C) +#define SHDW_DPI_H_TIMING (0x0110) +#define SHDW_DPI_V_TIMING (0x0114) +#define DISPC_TE_SYNC_DELAY (0x00bc) + +#define SPRD_LCDC_BASE g_dispc_base_addr + +#define SPRD_DISPC_BASE SPRD_LCDC_BASE +#define IRQ_DISPC_INT IRQ_DISPC0_INT + +#define REG_AHB_SOFT_RST (0x4 + SPRD_AHB_BASE) + +#define DISPC_CORE_EN (REG_AP_APB_APB_EB) +#define BIT_DISPC_CORE_EN (BIT_AP_CKG_EB) + +extern unsigned long g_dispc_base_addr; + + +enum{ + DISPC_IF_DBI = 0, + DISPC_IF_DPI, + DISPC_IF_EDPI, + DISPC_IF_LIMIT +}; + +static inline uint32_t dispc_read(uint32_t reg) +{ + return sci_glb_read(SPRD_DISPC_BASE + reg, 0xffffffff); +} + +static inline void dispc_write(uint32_t value, uint32_t reg) +{ + sci_glb_write((SPRD_DISPC_BASE + reg), value, 0xffffffff); +} + +static inline void dispc_set_bits(uint32_t bits, uint32_t reg) +{ + dispc_write(dispc_read(reg) | bits, reg); +} + +static inline void dispc_clear_bits(uint32_t bits, uint32_t reg) +{ + dispc_write(dispc_read(reg) & ~bits, reg); +} + +#endif diff --git a/drivers/autotst/dsi.c b/drivers/autotst/dsi.c new file mode 100644 index 00000000..ce4e9d97 --- /dev/null +++ b/drivers/autotst/dsi.c @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 "lcd_dummy.h" + +#include "mipi_dsih_local.h" +#include "mipi_dsih_dphy.h" +#include "mipi_dsih_hal.h" +#include "mipi_dsih_api.h" + +#define pr_debug printk + +#define DSI_PHY_REF_CLOCK (26*1000) +#define DSI_EDPI_CFG (0x6c) + +#ifdef CONFIG_FB_SCX15 +#define DISPC_DPI_CLOCK (192*1000000/18) +#else +#define DISPC_DPI_CLOCK (384*1000000/36) +#endif + +#define SPRD_MIPI_DSIC_BASE SPRD_DSI_BASE +#define IRQ_DSI_INTN0 IRQ_DSI0_INT +#define IRQ_DSI_INTN1 IRQ_DSI1_INT + +#define DSI_REG_EB REG_AP_AHB_AHB_EB +#define DSI_BIT_EB BIT_DSI_EB + +#define DSI_AHB_SOFT_RST REG_AP_AHB_AHB_RST +#define SPRD_DSI_BASE g_dsi_base_addr + +extern unsigned long g_dsi_base_addr; + + +struct autotst_dsi_context { + struct clk *clk_dsi; + bool is_inited; + uint32_t status;/*0- normal, 1- uninit, 2-abnormal*/ + dsih_ctrl_t dsi_inst; +}; + +static struct autotst_dsi_context autotst_dsi_ctx; + +static uint32_t dsi_core_read_function(uint32_t addr, uint32_t offset) +{ + return sci_glb_read(addr + offset, 0xffffffff); +} + +static void dsi_core_write_function(uint32_t addr, uint32_t offset, uint32_t data) +{ + sci_glb_write((addr + offset), data, 0xffffffff); +} + +static void dsi_core_or_function(unsigned int addr,unsigned int data) +{ + sci_glb_write(addr,(sci_glb_read(addr, 0xffffffff) | data), 0xffffffff); +} +static void dsi_core_and_function(unsigned int addr,unsigned int data) +{ + sci_glb_write(addr,(sci_glb_read(addr, 0xffffffff) & data), 0xffffffff); +} + +#if 0 +static irqreturn_t dsi_isr0(int irq, void *data) +{ + uint32_t reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST0); + printk(KERN_ERR "autotst_dsi: [%s](0x%x)!\n", __FUNCTION__, reg_val); + return IRQ_HANDLED; +} + +static irqreturn_t dsi_isr1(int irq, void *data) +{ + uint32_t reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST1); + printk(KERN_ERR "autotst_dsi: [%s](0x%x)!\n", __FUNCTION__, reg_val); + return IRQ_HANDLED; +} +#endif + +static int32_t dsi_edpi_setbuswidth(struct info_mipi * mipi) +{ + dsih_color_coding_t color_coding = 0; + + switch(mipi->video_bus_width){ + case 16: + color_coding = COLOR_CODE_16BIT_CONFIG1; + break; + case 18: + color_coding = COLOR_CODE_18BIT_CONFIG1; + break; + case 24: + color_coding = COLOR_CODE_24BIT; + break; + default: + printk(KERN_ERR "autotst_dsi:[%s] fail, invalid video_bus_width\n", __FUNCTION__); + return 0; + } + +#ifdef FB_DSIH_VERSION_1P21A + dsi_core_and_function((SPRD_MIPI_DSIC_BASE+R_DSI_HOST_DPI_COLOR_CODE),0xfffffff0); + dsi_core_or_function((SPRD_MIPI_DSIC_BASE+R_DSI_HOST_DPI_COLOR_CODE),color_coding); +#else + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_DPI_CFG, ((uint32_t)color_coding<<2)); +#endif + return 0; +} + + +static int32_t dsi_edpi_init(void) +{ +#ifdef FB_DSIH_VERSION_1P21A + dsi_core_write_function((uint32_t)SPRD_MIPI_DSIC_BASE, (uint32_t)R_DSI_HOST_EDPI_CMD_SIZE, 0x500); +#else + dsi_core_write_function((uint32_t)SPRD_MIPI_DSIC_BASE, (uint32_t)DSI_EDPI_CFG, 0x10500); +#endif + return 0; +} + +static int32_t dsi_dpi_init(struct panel_spec* panel) +{ + dsih_dpi_video_t dpi_param; + dsih_error_t result; + struct info_mipi * mipi = panel->info.mipi; + + dpi_param.no_of_lanes = mipi->lan_number; + dpi_param.byte_clock = mipi->phy_feq / 8; + dpi_param.pixel_clock = DISPC_DPI_CLOCK / 1000; +#ifdef FB_DSIH_VERSION_1P21A + dpi_param.max_hs_to_lp_cycles = 4;//110; + dpi_param.max_lp_to_hs_cycles = 15;//10; +#endif + + switch(mipi->video_bus_width){ + case 16: + dpi_param.color_coding = COLOR_CODE_16BIT_CONFIG1; + break; + case 18: + dpi_param.color_coding = COLOR_CODE_18BIT_CONFIG1; + break; + case 24: + dpi_param.color_coding = COLOR_CODE_24BIT; + break; + default: + printk(KERN_ERR "autotst_dsi:[%s] fail, invalid video_bus_width\n", __FUNCTION__); + break; + } + + if(SPRDFB_POLARITY_POS == mipi ->h_sync_pol){ + dpi_param.h_polarity = 1; + } + + if(SPRDFB_POLARITY_POS == mipi ->v_sync_pol){ + dpi_param.v_polarity = 1; + } + + if(SPRDFB_POLARITY_POS == mipi ->de_pol){ + dpi_param.data_en_polarity = 1; + } + + dpi_param.h_active_pixels = panel->width; + dpi_param.h_sync_pixels = mipi->timing->hsync; + dpi_param.h_back_porch_pixels = mipi->timing->hbp; + dpi_param.h_total_pixels = panel->width + mipi->timing->hsync + mipi->timing->hbp + mipi->timing->hfp; + + dpi_param.v_active_lines = panel->height; + dpi_param.v_sync_lines = mipi->timing->vsync; + dpi_param.v_back_porch_lines = mipi->timing->vbp; + dpi_param.v_total_lines = panel->height + mipi->timing->vsync + mipi->timing->vbp + mipi->timing->vfp; + + dpi_param.receive_ack_packets = 0; + dpi_param.video_mode = VIDEO_BURST_WITH_SYNC_PULSES; + dpi_param.virtual_channel = 0; + dpi_param.is_18_loosely = 0; + + result = mipi_dsih_dpi_video(&(autotst_dsi_ctx.dsi_inst), &dpi_param); + if(result != OK){ + printk(KERN_ERR "autotst_dsi: [%s] mipi_dsih_dpi_video fail (%d)!\n", __FUNCTION__, result); + return -1; + } + + return 0; +} + +static void dsi_log_error(const char * string) +{ + printk(string); +} + +static int32_t dsi_module_init(struct panel_spec *panel) +{ + int ret = 0; + dsih_ctrl_t* dsi_instance = &(autotst_dsi_ctx.dsi_inst); + dphy_t *phy = &(dsi_instance->phy_instance); + struct info_mipi * mipi = panel->info.mipi; + + pr_debug(KERN_INFO "autotst_dsi:[%s]\n", __FUNCTION__); + + if(autotst_dsi_ctx.is_inited){ + printk(KERN_INFO "autotst_dsi: dsi_module_init. is_inited==true!"); + return 0; + } + else{ + printk(KERN_INFO "autotst_dsi: dsi_module_init. call only once!\n"); + } + + phy->address = SPRD_MIPI_DSIC_BASE; + phy->core_read_function = dsi_core_read_function; + phy->core_write_function = dsi_core_write_function; + phy->log_error = dsi_log_error; + phy->log_info = NULL; + phy->reference_freq = DSI_PHY_REF_CLOCK; + + dsi_instance->address = SPRD_MIPI_DSIC_BASE; + dsi_instance->color_mode_polarity =mipi->color_mode_pol; + dsi_instance->shut_down_polarity = mipi->shut_down_pol; + dsi_instance->core_read_function = dsi_core_read_function; + dsi_instance->core_write_function = dsi_core_write_function; + dsi_instance->log_error = dsi_log_error; + dsi_instance->log_info = NULL; + /*in our rtl implementation, this is max rd time, not bta time and use 15bits*/ + dsi_instance->max_bta_cycles = 0x6000;//10; +#ifndef FB_DSIH_VERSION_1P21A + dsi_instance->max_hs_to_lp_cycles = 4;//110; + dsi_instance->max_lp_to_hs_cycles = 15;//10; +#endif + dsi_instance->max_lanes = mipi->lan_number; +#if 0 + ret = request_irq(IRQ_DSI_INTN0, dsi_isr0, IRQF_DISABLED, "DSI_INT0", &autotst_dsi_ctx); + if (ret) { + printk(KERN_ERR "autotst_dsi: dsi failed to request irq int0!\n"); + }else{ + printk(KERN_ERR "autotst_dsi: dsi request irq int0 OK!\n"); + } + + ret = request_irq(IRQ_DSI_INTN1, dsi_isr1, IRQF_DISABLED, "DSI_INT1", &autotst_dsi_ctx); + if (ret) { + printk(KERN_ERR "autotst_dsi: dsi failed to request irq int1!\n"); + }else{ + printk(KERN_ERR "autotst_dsi: dsi request irq int1 OK!\n"); + } +#endif + autotst_dsi_ctx.is_inited = true; + + return 0; +} + +static int32_t dsih_init(struct panel_spec *panel) +{ + dsih_error_t result = OK; + dsih_ctrl_t* dsi_instance = &(autotst_dsi_ctx.dsi_inst); + dphy_t *phy = &(dsi_instance->phy_instance); + struct info_mipi * mipi = panel->info.mipi; + int i = 0; +#ifdef FB_DSIH_VERSION_1P21A + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK0, 0x1fffff); + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK1, 0x3ffff); +#else + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK0, 0x1fffff); + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK1, 0x3ffff); +#endif + + if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){ + dsi_edpi_init(); + } + +#ifndef FB_DSIH_VERSION_1P21A + dsi_instance->phy_feq = panel->info.mipi->phy_feq; +#endif + result = mipi_dsih_open(dsi_instance); + if(OK != result){ + printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_open fail (%d)!\n", __FUNCTION__, result); + autotst_dsi_ctx.status = 1; + return -1; + } + + result = mipi_dsih_dphy_configure(phy, mipi->lan_number, mipi->phy_feq); + if(OK != result){ + printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_dphy_configure fail (%d)!\n", __FUNCTION__, result); + autotst_dsi_ctx.status = 1; + return -1; + } + + while(5 != (dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_STATUS) & 5)){ + if(0x0 == ++i%500000){ + printk("autotst_dsi: [%s] warning: busy waiting!\n", __FUNCTION__); + } + } + + if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){ + dsi_edpi_setbuswidth(mipi); + } + + result = mipi_dsih_enable_rx(dsi_instance, 1); + if(OK != result){ + printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_enable_rx fail (%d)!\n", __FUNCTION__, result); + autotst_dsi_ctx.status = 1; + return -1; + } + + result = mipi_dsih_ecc_rx(dsi_instance, 1); + if(OK != result){ + printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_ecc_rx fail (%d)!\n", __FUNCTION__, result); + autotst_dsi_ctx.status = 1; + return -1; + } + + result = mipi_dsih_eotp_rx(dsi_instance, 1); + if(OK != result){ + printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_eotp_rx fail (%d)!\n", __FUNCTION__, result); + autotst_dsi_ctx.status = 1; + return -1; + } + + result = mipi_dsih_eotp_tx(dsi_instance, 1); + if(OK != result){ + printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_eotp_tx fail (%d)!\n", __FUNCTION__, result); + autotst_dsi_ctx.status = 1; + return -1; + } + + if(SPRDFB_MIPI_MODE_VIDEO == mipi->work_mode){ + dsi_dpi_init(panel); + } + +#ifdef FB_DSIH_VERSION_1P21A + mipi_dsih_dphy_enable_nc_clk(&(dsi_instance->phy_instance), false); +#endif + autotst_dsi_ctx.status = 0; + + return 0; +} + +static void dsi_enable(void) +{ + sci_glb_set(REG_AP_AHB_MISC_CKG_EN, BIT_DPHY_REF_CKG_EN); + sci_glb_set(REG_AP_AHB_MISC_CKG_EN, BIT_DPHY_CFG_CKG_EN); + sci_glb_set(DSI_REG_EB, DSI_BIT_EB); +} + +static void dsi_disable(void) +{ + sci_glb_clr(REG_AP_AHB_MISC_CKG_EN, BIT_DPHY_REF_CKG_EN); + sci_glb_clr(REG_AP_AHB_MISC_CKG_EN, BIT_DPHY_CFG_CKG_EN); + sci_glb_clr(DSI_REG_EB, DSI_BIT_EB); +} + +static void dsi_reset(void) +{ + sci_glb_set(DSI_AHB_SOFT_RST, BIT_DSI_SOFT_RST); + udelay(10); + sci_glb_clr(DSI_AHB_SOFT_RST, BIT_DSI_SOFT_RST); +} + +static int32_t dsi_ready(struct panel_spec *panel) +{ + struct info_mipi * mipi = panel->info.mipi; + + if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){ + mipi_dsih_cmd_mode(&(autotst_dsi_ctx.dsi_inst), 1); +#ifdef FB_DSIH_VERSION_1P21A + mipi_dsih_dphy_enable_hs_clk(&(autotst_dsi_ctx.dsi_inst.phy_instance), true); +#else + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x1); + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, 0x1); +#endif + }else{ +#ifdef FB_DSIH_VERSION_1P21A + mipi_dsih_dphy_enable_hs_clk(&(autotst_dsi_ctx.dsi_inst.phy_instance), true); +#else + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, 0x1); +#endif + mipi_dsih_video_mode(&(autotst_dsi_ctx.dsi_inst), 1); + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PWR_UP, 0); + udelay(100); + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PWR_UP, 1); + mdelay(3); +#ifdef FB_DSIH_VERSION_1P21A + dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_ST0); + dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_ST1); +#else + dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST0); + dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST1); +#endif + } + +#ifdef FB_DSIH_VERSION_1P21A + //dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK0, 0x0); + //dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK1, 0x800); +#else + //dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK0, 0x0); + //dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK1, 0x800); +#endif + return 0; +} + +void autotst_dsi_dump(void) +{ + int i = 0; + for(i=0;i<256;i+=16){ + printk("autotst_dsi: %x: 0x%x, 0x%x, 0x%x, 0x%x\n", i, dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i), + dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i+4), + dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i+8), + dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i+12)); + } + printk("**************************\n"); +} + +void autotst_dsi_dump1(void) +{ + int i = 0; + for(i=0;i<50;i++){ + printk("autotst_dsi: 0x%x\n", dsi_core_read_function(SPRD_MIPI_DSIC_BASE, 0x60)); + udelay(5); + } + printk("**************************\n"); +} + +int32_t autotst_dsi_init(struct panel_spec *panel) +{ + dsih_error_t result = OK; + + printk(KERN_INFO "autotst_dsi:[%s]\n", __FUNCTION__); + dsi_enable(); + dsi_reset(); + dsi_module_init(panel); + result=dsih_init(panel); + dsi_ready(panel); + + return result; +} + +int32_t autotst_dsi_uninit(void) +{ + dsih_error_t result; + dsih_ctrl_t* dsi_instance = &(autotst_dsi_ctx.dsi_inst); + + printk(KERN_INFO "autotst_dsi: [%s]\n",__FUNCTION__); + + dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, 0); + result = mipi_dsih_close(&(autotst_dsi_ctx.dsi_inst)); + dsi_instance->status = NOT_INITIALIZED; + + autotst_dsi_ctx.status = 1; + + if(OK != result){ + printk(KERN_ERR "autotst_dsi: [%s] fail (%d)!\n", __FUNCTION__, result); + return -1; + } + + mdelay(10); + dsi_disable(); + return 0; +} diff --git a/drivers/autotst/lcd_dummy.c b/drivers/autotst/lcd_dummy.c new file mode 100644 index 00000000..8db38899 --- /dev/null +++ b/drivers/autotst/lcd_dummy.c @@ -0,0 +1,109 @@ +/* drivers/video/sprdfb/lcd_ssd2075_mipi.c + * + * Support for ssd2075 mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 "lcd_dummy.h" +//#define printk printf + +/*mcu panel*/ +static struct timing_mcu lcd_dummy_mcu_timing = { + .rcss = 15, // 15ns + .rlpw = 60, + .rhpw = 60, + .wcss = 10, + .wlpw = 35, + .whpw = 35, +}; + +static struct info_mcu lcd_dummy_mcu_info = { + .bus_mode = LCD_BUS_8080, + .bus_width = 24, + .bpp = 24, /*RGB88*/ + .te_pol = SPRDFB_POLARITY_POS, + .te_sync_delay = 0, + .timing = &lcd_dummy_mcu_timing, +}; + +struct panel_spec lcd_dummy_mcu_spec = { + .width = 320, + .height = 480, + .type = LCD_MODE_MCU, + .info = { + .mcu = &lcd_dummy_mcu_info + }, +}; + +/*rgb panel*/ +static struct timing_rgb lcd_dummy_rgb_timing = { + .hfp = 30, /* unit: pixel */ + .hbp = 16, + .hsync = 1, + .vfp = 16, /*unit: line*/ + .vbp = 16, + .vsync = 1, +}; + +static struct info_rgb lcd_dummy_rgb_info = { + .video_bus_width = 24, /*18,16*/ + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .timing = &lcd_dummy_rgb_timing, +}; + +struct panel_spec lcd_dummy_rgb_spec = { + .width = 320, + .height = 480, + .type = LCD_MODE_RGB, + .info = { + .rgb = &lcd_dummy_rgb_info + }, +}; + +/*mipi panel*/ +static struct timing_rgb lcd_dummy_mipi_timing = { + .hfp =50, + .hbp = 36, + .hsync =16, + .vfp = 12, + .vbp = 14, + .vsync = 2, +}; + +static struct info_mipi lcd_dummy_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 4, + .phy_feq =100*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_dummy_mipi_timing, +}; + +struct panel_spec lcd_dummy_mipi_spec = { + .width = 320, + .height = 480, + .type = LCD_MODE_DSI, + .info = { + .mipi = &lcd_dummy_mipi_info + }, +}; + + diff --git a/drivers/autotst/lcd_dummy.h b/drivers/autotst/lcd_dummy.h new file mode 100644 index 00000000..44701652 --- /dev/null +++ b/drivers/autotst/lcd_dummy.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 _LCD_DUMMY_H_ +#define _LCD_DUMMY_H_ + +/* LCD mode */ +#define LCD_MODE_MCU 0 +#define LCD_MODE_RGB 1 +#define LCD_MODE_DSI 2 + +/* bus mode */ +#define LCD_BUS_8080 0 +#define LCD_BUS_6800 1 + +/* panel property */ +/* lcdc refresh, TE on, double timing, partial update*/ +#define PANEL_CAP_NORMAL 0x0 + +/* only not support partial update*/ +#define PANEL_CAP_NOT_PARTIAL_UPDATE 0x1 + +/* write register, grame have the same timing */ +#define PANEL_CAP_UNIQUE_TIMING 0x2 + +/* lcd not support TE */ +#define PANEL_CAP_NOT_TEAR_SYNC 0x4 + +/* only do command/data register, such as some mono oled display device */ +#define PANEL_CAP_MANUAL_REFRESH 0x8 + +enum{ + SPRDFB_PANEL_TYPE_MCU = 0, + SPRDFB_PANEL_TYPE_RGB, + SPRDFB_PANEL_TYPE_MIPI, + SPRDFB_PANEL_TYPE_LIMIT +}; + +enum{ + SPRDFB_POLARITY_POS = 0, + SPRDFB_POLARITY_NEG, + SPRDFB_POLARITY_LIMIT +}; + +enum{ + SPRDFB_MIPI_MODE_CMD = 0, + SPRDFB_MIPI_MODE_VIDEO, + SPRDFB_MIPI_MODE_LIMIT +}; + +/* MCU LCD specific properties */ +struct timing_mcu { + uint16_t rcss; /*unit: ns*/ + uint16_t rlpw; + uint16_t rhpw; + uint16_t wcss; + uint16_t wlpw; + uint16_t whpw; +}; + +/* RGB LCD specific properties */ +struct timing_rgb { + uint16_t hfp;/*unit: pixel*/ + uint16_t hbp; + uint16_t hsync; + uint16_t vfp; /*unit: line*/ + uint16_t vbp; + uint16_t vsync; +}; + +struct info_mipi { + uint16_t work_mode; /*command_mode, video_mode*/ + uint16_t video_bus_width; + uint32_t lan_number; + uint32_t phy_feq; /*unit:Hz*/ + uint16_t h_sync_pol; + uint16_t v_sync_pol; + uint16_t de_pol; + uint16_t te_pol; /*only for command_mode*/ + uint16_t color_mode_pol; + uint16_t shut_down_pol; + struct timing_rgb *timing; +}; + +struct info_rgb { + uint16_t video_bus_width; + uint16_t h_sync_pol; + uint16_t v_sync_pol; + uint16_t de_pol; + struct timing_rgb *timing; +}; + +struct info_mcu { + uint16_t bus_mode; /*8080, 6800*/ + uint16_t bus_width; + uint16_t bpp; + uint16_t te_pol; + uint32_t te_sync_delay; + struct timing_mcu *timing; +}; + +/* LCD abstraction */ +struct panel_spec { + uint32_t cap; + uint16_t width; + uint16_t height; + uint16_t type; /*mcu, rgb, mipi*/ + union { + struct info_mcu *mcu; + struct info_rgb *rgb; + struct info_mipi * mipi; + } info; +}; + +#endif diff --git a/drivers/autotst/lcdc.c b/drivers/autotst/lcdc.c new file mode 100644 index 00000000..2c61701e --- /dev/null +++ b/drivers/autotst/lcdc.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 "lcdc_reg.h" + + +//#define LCDC_DEBUG +#ifdef LCDC_DEBUG +#define LCDC_PRINT printk +#else +#define LCDC_PRINT(...) +#endif + + +int32_t lcm_send_cmd (uint32_t cmd) +{ + /* wait for that the ahb enter idle state */ + while(lcdc_read(LCM_CTRL) & BIT(20)); + + lcdc_write(cmd, LCM_CMD); + return 0; +} + +int32_t lcm_send_cmd_data (uint32_t cmd, uint32_t data) +{ + /* wait for that the ahb enter idle state */ + while(lcdc_read(LCM_CTRL) & BIT(20)); + + lcdc_write(cmd, LCM_CMD); + + /* wait for that the ahb enter idle state */ + while(lcdc_read(LCM_CTRL) & BIT(20)); + + lcdc_write(data, LCM_DATA); + return 0; +} + +int32_t lcm_send_data (uint32_t data) +{ + /* wait for that the ahb enter idle state */ + while(lcdc_read(LCM_CTRL) & BIT(20)); + + lcdc_write(data, LCM_DATA); + return 0; +} + +uint32_t lcm_read_data (void) +{ + /* wait for that the ahb enter idle state */ + while(lcdc_read(LCM_CTRL) & BIT(20)); + lcdc_write(1 << 24, LCM_DATA); + udelay(50); + return lcdc_read(LCM_RDDATA); +} + +static struct clk * s_lcdcclk = NULL; + +int lcm_init(void) +{ + //int i; + unsigned int ctrl; + + if( NULL == s_lcdcclk ) { + s_lcdcclk = clk_get(NULL, "clk_lcdc"); + } + if( s_lcdcclk == NULL ) { + printk(KERN_ERR "can not get clk_lcdc!!!!!\n"); + return -EFAULT; + } + + clk_enable(s_lcdcclk); + + ctrl = lcdc_read(LCM_CTRL); + printk("reg[LCM_CTRL] = %x\n", ctrl); + + ctrl &= 0x10000; + ctrl |= 0x02828; // bus&pixel are 24bits + + lcdc_write(ctrl, LCM_CTRL); + + //lcdc_write((1 << 8) | (5 << 4) | 5, LCM_TIMING0); + //lcdc_write((1 << 8) | (5 << 4) | 5, LCM_TIMING1); + + //for( i = LCM_CTRL; i <= LCM_RSTN; i += 4 ) { + // printk("reg[%x] = %x\n", i, lcdc_read(i)); + //} + + return 0; +} + +int lcm_close(void) +{ + if( NULL != s_lcdcclk ) { + clk_disable(s_lcdcclk); + } + printk("lcm_close \n"); + return 0; +} + + diff --git a/drivers/autotst/lcdc_reg.h b/drivers/autotst/lcdc_reg.h new file mode 100644 index 00000000..cd190dd8 --- /dev/null +++ b/drivers/autotst/lcdc_reg.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 _LCDC_REG_H_ +#define _LCDC_REG_H_ + +#include + +#define AHB_CTL0 (SPRD_AHB_BASE + 0x200) +#define AHB_SOFT_RST (SPRD_AHB_BASE + 0x210) + +/* LCDC regs offset */ +#define LCDC_CTRL (0x0000) +#define LCDC_DISP_SIZE (0x0004) +#define LCDC_LCM_START (0x0008) +#define LCDC_LCM_SIZE (0x000c) +#define LCDC_BG_COLOR (0x0010) +#define LCDC_FIFO_STATUS (0x0014) + +#define LCDC_IMG_CTRL (0x0020) +#define LCDC_IMG_Y_BASE_ADDR (0x0024) +#define LCDC_IMG_UV_BASE_ADDR (0x0028) +#define LCDC_IMG_SIZE_XY (0x002c) +#define LCDC_IMG_PITCH (0x0030) +#define LCDC_IMG_DISP_XY (0x0034) + +#define LCDC_OSD1_CTRL (0x0050) +#define LCDC_OSD2_CTRL (0x0080) +#define LCDC_OSD3_CTRL (0x00b0) +#define LCDC_OSD4_CTRL (0x00e0) +#define LCDC_OSD5_CTRL (0x0110) + +#define LCDC_OSD1_BASE_ADDR (0x0054) +#define LCDC_OSD1_ALPHA_BASE_ADDR (0x0058) +#define LCDC_OSD1_SIZE_XY (0x005c) +#define LCDC_OSD1_PITCH (0x0060) +#define LCDC_OSD1_DISP_XY (0x0064) +#define LCDC_OSD1_ALPHA (0x0068) +#define LCDC_OSD1_GREY_RGB (0x006c) +#define LCDC_OSD1_CK (0x0070) + +#define LCDC_OSD2_BASE_ADDR (0x0084) +#define LCDC_OSD2_SIZE_XY (0x008c) +#define LCDC_OSD2_PITCH (0x0090) +#define LCDC_OSD2_DISP_XY (0x0094) +#define LCDC_OSD2_ALPHA (0x0098) +#define LCDC_OSD2_GREY_RGB (0x009c) +#define LCDC_OSD2_CK (0x00a0) + +#define LCDC_IRQ_EN (0x0170) +#define LCDC_IRQ_CLR (0x0174) +#define LCDC_IRQ_STATUS (0x0178) +#define LCDC_IRQ_RAW (0x017c) + +#define LCM_CTRL (0x0180) +#define LCM_TIMING0 (0x0184) +#define LCM_TIMING1 (0x0188) +#define LCM_RDDATA (0x018c) +#define LCM_RSTN (0x0190) +#define LCM_CMD (0x01A0) +#define LCM_DATA (0x01A4) + +extern unsigned long g_dispc_base_addr; + +static inline uint32_t lcdc_read(uint32_t reg) +{ + return __raw_readl(SPRD_LCDC_BASE + reg); +} + +static inline void lcdc_write(uint32_t value, uint32_t reg) +{ + __raw_writel(value, (SPRD_LCDC_BASE + reg)); +} + +static inline void lcdc_set_bits(uint32_t bits, uint32_t reg) +{ + lcdc_write(lcdc_read(reg) | bits, reg); +} + +static inline void lcdc_clear_bits(uint32_t bits, uint32_t reg) +{ + lcdc_write(lcdc_read(reg) & ~bits, reg); +} + +#endif diff --git a/drivers/autotst/mipi_dsih_api.c b/drivers/autotst/mipi_dsih_api.c new file mode 100644 index 00000000..b8904d81 --- /dev/null +++ b/drivers/autotst/mipi_dsih_api.c @@ -0,0 +1,1708 @@ +#include "mipi_dsih_api.h" +#include "mipi_dsih_hal.h" +#include "mipi_dsih_dphy.h" +#include + +/* whether to get debug messages (1) or not (0) */ +#define DEBUG 0 + +#define PRECISION_FACTOR 1000 +#define VIDEO_PACKET_OVERHEAD 6 +#define NULL_PACKET_OVERHEAD 6 +#define SHORT_PACKET 4 +#define BLANKING_PACKET 6 +/** Version supported by this driver */ +static const uint32_t mipi_dsih_supported_versions[] = {0x3132302A, 0x3132312A}; +static const uint32_t mipi_dsih_no_of_versions = sizeof(mipi_dsih_supported_versions) / sizeof(uint32_t); + +/** + * Open controller instance + * - Check if driver is compatible with core version + * - Check if instance context data structure is not NULL + * - Bring up PHY for any transmissions in low power + * + Includes programming PLL to DEFAULT_BYTE_CLOCK + * - Bring up controller and perform initial configuration + * + Includes start all commands transmision in LP + * + Controller will not turn the bus around after commands + * + program counters + * @param instance pointer to structure holding the DSI Host core information + * @return dsih_error_t + * @note this function must be called before any other function in this API + */ +dsih_error_t mipi_dsih_open(dsih_ctrl_t * instance) +{ + dsih_error_t err = OK; + uint32_t version = 0; + int i = 0; + + if (instance == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + else if ((instance->core_read_function == 0) || (instance->core_write_function == 0)) + { + return ERR_DSI_INVALID_IO; + } + else if (instance->status == INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + else if (mipi_dsih_dphy_open(&(instance->phy_instance))) + { + return ERR_DSI_PHY_INVALID; + } + else + { + instance->status = NOT_INITIALIZED; + version = mipi_dsih_hal_get_version(instance); + for (i = 0; i < mipi_dsih_no_of_versions; i++) + { + if (version == mipi_dsih_supported_versions[i]) + { + break; + } + } + /* no matching supported version has been found*/ + if (i >= mipi_dsih_no_of_versions) + { + if (instance->log_info != 0) + { + instance->log_info("sprdfb: driver does not support this core version 0x%lX", version); + } + return ERR_DSI_CORE_INCOMPATIBLE; + } + } + mipi_dsih_hal_power(instance, 0); + //mipi_dsih_hal_power(instance, 0);//Jessica + //mipi_dsih_hal_power(instance, 1);//Jessica + mipi_dsih_hal_dpi_color_mode_pol(instance, !instance->color_mode_polarity); + mipi_dsih_hal_dpi_shut_down_pol(instance, !instance->shut_down_polarity); + //err = mipi_dsih_phy_hs2lp_config(instance, instance->max_hs_to_lp_cycles); + //err |= mipi_dsih_phy_lp2hs_config(instance, instance->max_lp_to_hs_cycles); + mipi_dsih_hal_int_mask_0(instance, 0xffffff); + mipi_dsih_hal_int_mask_1(instance, 0xffffff); + err = mipi_dsih_phy_bta_time(instance, instance->max_bta_cycles); + if (err) + { + return ERR_DSI_OVERFLOW; + } + /* by default, return to LP during ALL, unless otherwise specified*/ + mipi_dsih_hal_dpi_lp_during_hfp(instance, 1); + mipi_dsih_hal_dpi_lp_during_hbp(instance, 1); + mipi_dsih_hal_dpi_lp_during_vactive(instance, 1); + mipi_dsih_hal_dpi_lp_during_vfp(instance, 1); + mipi_dsih_hal_dpi_lp_during_vbp(instance, 1); + mipi_dsih_hal_dpi_lp_during_vsync(instance, 1); + /* by default, all commands are sent in LP */ + mipi_dsih_hal_dcs_wr_tx_type(instance, 0, 1); + mipi_dsih_hal_dcs_wr_tx_type(instance, 1, 1); + mipi_dsih_hal_dcs_wr_tx_type(instance, 3, 1); /* long packet*/ + mipi_dsih_hal_dcs_rd_tx_type(instance, 0, 1); + /*Jessica add to support max rd packet size command*/ + mipi_dsih_hal_max_rd_packet_size_type(instance, 1); + mipi_dsih_hal_gen_wr_tx_type(instance, 0, 1); + mipi_dsih_hal_gen_wr_tx_type(instance, 1, 1); + mipi_dsih_hal_gen_wr_tx_type(instance, 2, 1); + mipi_dsih_hal_gen_wr_tx_type(instance, 3, 1); /* long packet*/ + mipi_dsih_hal_gen_rd_tx_type(instance, 0, 1); + mipi_dsih_hal_gen_rd_tx_type(instance, 1, 1); + mipi_dsih_hal_gen_rd_tx_type(instance, 2, 1); + /* by default, RX_VC = 0, NO EOTp, EOTn, BTA, ECC rx and CRC rx */ + mipi_dsih_hal_gen_rd_vc(instance, 0); + mipi_dsih_hal_gen_eotp_rx_en(instance, 0); + mipi_dsih_hal_gen_eotp_tx_en(instance, 0); + mipi_dsih_hal_bta_en(instance, 0); + mipi_dsih_hal_gen_ecc_rx_en(instance, 0); + mipi_dsih_hal_gen_crc_rx_en(instance, 0); + //mipi_dsih_hal_power(instance, 0);//Jessica + mipi_dsih_hal_power(instance, 1);//Jessica + + /* dividing by 6 is aimed for max PHY frequency, 1GHz */ + mipi_dsih_hal_tx_escape_division(instance, 4); //6 //Jessica + instance->status = INITIALIZED; + /* initialize pll so escape clocks could be generated at 864MHz, 1 lane */ + /* however the high speed clock will not be requested */ + //err = mipi_dsih_dphy_configure(&(instance->phy_instance), 1, DEFAULT_BYTE_CLOCK); + return err; +} +/** + * Close DSI Host driver + * - Free up resources and shutdown host controller and PHY + * @param instance pointer to structure holding the DSI Host core information + * @return dsih_error_t + */ +dsih_error_t mipi_dsih_close(dsih_ctrl_t * instance) +{ + if (instance == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (instance->status != INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + mipi_dsih_hal_int_mask_0(instance, 0xffffff); + mipi_dsih_hal_int_mask_1(instance, 0xffffff); + mipi_dsih_dphy_close(&(instance->phy_instance)); + mipi_dsih_hal_power(instance, 0); + instance->status = NOT_INITIALIZED; + return OK; +} +/** + * Enable return to low power mode inside video periods when timing allows + * @param instance pointer to structure holding the DSI Host core information + * @param hfp allow to return to lp inside horizontal front porch pixels + * @param hbp allow to return to lp inside horizontal back porch pixels + * @param vactive allow to return to lp inside vertical active lines + * @param vfp allow to return to lp inside vertical front porch lines + * @param vbp allow to return to lp inside vertical back porch lines + * @param vsync allow to return to lp inside vertical sync lines + */ +void mipi_dsih_allow_return_to_lp(dsih_ctrl_t * instance, int hfp, int hbp, int vactive, int vfp, int vbp, int vsync) +{ + if(0 == instance) + { + return; + } + + if (instance->status == INITIALIZED) + { + mipi_dsih_hal_dpi_lp_during_hfp(instance, hfp); + mipi_dsih_hal_dpi_lp_during_hbp(instance, hbp); + mipi_dsih_hal_dpi_lp_during_vactive(instance, vactive); + mipi_dsih_hal_dpi_lp_during_vfp(instance, vfp); + mipi_dsih_hal_dpi_lp_during_vbp(instance, vbp); + mipi_dsih_hal_dpi_lp_during_vsync(instance, vsync); + return; + } + if (instance->log_error != 0) + { + instance->log_error("sprdfb: [mipi_dsih_allow_return_to_lp] invalid instance"); + } + +} +/** + * Set DCS command packet transmission to low power + * @param instance pointer to structure holding the DSI Host core information + * @param long_write command packets + * @param short_write command packets with none and one parameters + * @param short_read command packets with none parameters + */ +void mipi_dsih_dcs_cmd_lp_transmission(dsih_ctrl_t * instance, int long_write, int short_write, int short_read) +{ + if(0 == instance) + { + return; + } + + if (instance->status == INITIALIZED) + { + mipi_dsih_hal_dcs_wr_tx_type(instance, 0, short_write); + mipi_dsih_hal_dcs_wr_tx_type(instance, 1, short_write); + mipi_dsih_hal_dcs_wr_tx_type(instance, 3, long_write); /* long packet*/ + mipi_dsih_hal_dcs_rd_tx_type(instance, 0, short_read); + return; + } + if (instance->log_error != 0) + { + instance->log_error("sprdfb: [mipi_dsih_dcs_cmd_lp_transmission] invalid instance"); + } + +} +/** + * Set Generic interface packet transmission to low power + * @param instance pointer to structure holding the DSI Host core information + * @param long_write command packets + * @param short_write command packets with none, one and two parameters + * @param short_read command packets with none, one and two parameters + */ +void mipi_dsih_gen_cmd_lp_transmission(dsih_ctrl_t * instance, int long_write, int short_write, int short_read) +{ + if(0 == instance) + { + return; + } + + if (instance->status == INITIALIZED) + { + mipi_dsih_hal_gen_wr_tx_type(instance, 0, short_write); + mipi_dsih_hal_gen_wr_tx_type(instance, 1, short_write); + mipi_dsih_hal_gen_wr_tx_type(instance, 2, short_write); + mipi_dsih_hal_gen_wr_tx_type(instance, 3, long_write); /* long packet*/ + mipi_dsih_hal_gen_rd_tx_type(instance, 0, short_read); + mipi_dsih_hal_gen_rd_tx_type(instance, 1, short_read); + mipi_dsih_hal_gen_rd_tx_type(instance, 2, short_read); + return; + } + if (instance->log_error != 0) + { + instance->log_error("sprdfb: [mipi_dsih_gen_cmd_lp_transmission] invalid instance"); + } + +} +/* packet handling */ +/** + * Enable all receiving activities (applying a Bus Turn Around). + * - Disabling using this function will stop all acknowledges by the + * peripherals and no interrupts from low-level protocol error reporting + * will be able to rise. + * - Enabling any receiving function (command or frame ACKs, ECC, + * tear effect ACK or EoTp receiving) will enable this automatically, + * but it must be EXPLICITLY be disabled to disabled all kinds of + * receiving functionality. + * @param instance pointer to structure holding the DSI Host core information + * @param enable or disable + * @return error code + */ +dsih_error_t mipi_dsih_enable_rx(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_hal_bta_en(instance, enable); + return OK; +} +/** + * Enable command packet acknowledges by the peripherals + * - For interrupts to rise the monitored event must be registered + * using the event_register function + * @param instance pointer to structure holding the DSI Host core information + * @param enable or disable + * @return error code + */ +dsih_error_t mipi_dsih_peripheral_ack(dsih_ctrl_t * instance, int enable) +{ + if (instance != 0) + { + if (instance->status == INITIALIZED) + { + mipi_dsih_hal_cmd_ack_en(instance, enable); + if (enable) + { + mipi_dsih_hal_bta_en(instance, 1); + } + return OK; + } + } + return ERR_DSI_INVALID_INSTANCE; +} +/** + * Enable tearing effect acknowledges by the peripherals (wait for TE) + * - It enables the following from the DSI specification + * "Since the timing of a TE event is, by definition, unknown to the host + * processor, the host processor shall give bus possession to the display + * module and then wait for up to one video frame period for the TE response. + * During this time, the host processor cannot send new commands, or requests + * to the display module, because it does not have bus possession." + * @param instance pointer to structure holding the DSI Host core information + * @param enable or disable + * @return error code + */ +dsih_error_t mipi_dsih_tear_effect_ack(dsih_ctrl_t * instance, int enable) +{ + if (instance != 0) + { + if (instance->status == INITIALIZED) + { + mipi_dsih_hal_tear_effect_ack_en(instance, enable); + if (enable) + { + mipi_dsih_hal_bta_en(instance, 1); + } + return OK; + } + } + return ERR_DSI_INVALID_INSTANCE; +} +/** + * Enable the receiving of EoT packets at the end of LS transmission. + * @param instance pointer to structure holding the DSI Host core information + * @param enable or disable + * @return error code + */ +dsih_error_t mipi_dsih_eotp_rx(dsih_ctrl_t * instance, int enable) +{ + if (instance != 0) + { + if (instance->status == INITIALIZED) + { + mipi_dsih_hal_gen_eotp_rx_en(instance, enable); + if (enable) + { + mipi_dsih_hal_bta_en(instance, 1); + } + return OK; + } + } + return ERR_DSI_INVALID_INSTANCE; +} +/** + * Enable the listening to ECC bytes. This allows for recovering from + * 1 bit errors. To report ECC events, the ECC events should be registered + * @param instance pointer to structure holding the DSI Host core information + * @param enable or disable + * @return error code + */ +dsih_error_t mipi_dsih_ecc_rx(dsih_ctrl_t * instance, int enable) +{ + if (instance != 0) + { + if (instance->status == INITIALIZED) + { + mipi_dsih_hal_gen_ecc_rx_en(instance, enable); + if (enable) + { + mipi_dsih_hal_bta_en(instance, 1); + } + return OK; + } + } + return ERR_DSI_INVALID_INSTANCE; +} +/** + * Enable the sending of EoT (End of Transmission) packets at the end of HS + * transmission. It was made optional in the DSI spec. for retro-compatibility. + * @param instance pointer to structure holding the DSI Host core information + * @param enable or disable + * @return error code + */ +dsih_error_t mipi_dsih_eotp_tx(dsih_ctrl_t * instance, int enable) +{ + if (instance != 0) + { + if (instance->status == INITIALIZED) + { + mipi_dsih_hal_gen_eotp_tx_en(instance, enable); + return OK; + } + } + return ERR_DSI_INVALID_INSTANCE; +} +/** + * Configure DPI video interface + * - If not in burst mode, it will compute the video and null packet sizes + * according to necessity + * - Configure timers for data lanes and/or clock lane to return to LP when + * bandwidth is not filled by data + * @param instance pointer to structure holding the DSI Host core information + * @param video_params pointer to video stream-to-send information + * @return error code + */ +dsih_error_t mipi_dsih_dpi_video(dsih_ctrl_t * instance, dsih_dpi_video_t * video_params) +{ + dsih_error_t err_code = OK; + uint16_t bytes_per_pixel_x100 = 0; /* bpp x 100 because it can be 2.25 */ + uint16_t video_size = 0; + uint32_t ratio_clock_xPF = 0; /* holds dpi clock/byte clock times precision factor */ + uint16_t null_packet_size = 0; + uint8_t video_size_step = 1; + uint32_t hs_timeout = 0; + uint32_t total_bytes = 0; + uint32_t bytes_per_chunk = 0; + uint32_t no_of_chunks = 0; + uint32_t bytes_left = 0; + uint32_t chunk_overhead = 0; + int counter = 0; + /* check DSI controller instance */ + if ((instance == 0) || (video_params == 0)) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (instance->status != INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (video_params->no_of_lanes > instance->max_lanes) + { + return ERR_DSI_OUT_OF_BOUND; + } + /* set up phy pll to required lane clock */ + err_code = mipi_dsih_phy_hs2lp_config(instance, video_params->max_hs_to_lp_cycles); + err_code |= mipi_dsih_phy_lp2hs_config(instance, video_params->max_lp_to_hs_cycles); + err_code = mipi_dsih_phy_clk_hs2lp_config(instance, video_params->max_clk_hs_to_lp_cycles); + err_code |= mipi_dsih_phy_clk_lp2hs_config(instance, video_params->max_clk_lp_to_hs_cycles); + video_params->non_continuous_clock = 0; // 1.21a new feature, set 1 result in half-bottom snow screen , disbale it + mipi_dsih_non_continuous_clock(instance,video_params->non_continuous_clock); + //begin--frank + //err_code = mipi_dsih_dphy_configure(&(instance->phy_instance), video_params->no_of_lanes, video_params->byte_clock * 8); + //if (err_code) + //{ + // return err_code; + //} + //end--frank + ratio_clock_xPF = (video_params->byte_clock * PRECISION_FACTOR) / (video_params->pixel_clock); + video_size = video_params->h_active_pixels; + /* set up ACKs and error reporting */ + mipi_dsih_hal_dpi_frame_ack_en(instance, video_params->receive_ack_packets); + if (video_params->receive_ack_packets) + { /* if ACK is requested, enable BTA, otherwise leave as is */ + mipi_dsih_hal_bta_en(instance, 1); + } + /* mipi_dsih_hal_gen_cmd_mode_en(instance, 0); */ + mipi_dsih_hal_dpi_video_mode_en(instance, 1); + /* get bytes per pixel and video size step (depending if loosely or not */ + switch (video_params->color_coding) + { + case COLOR_CODE_16BIT_CONFIG1: + case COLOR_CODE_16BIT_CONFIG2: + case COLOR_CODE_16BIT_CONFIG3: + bytes_per_pixel_x100 = 200; + video_size_step = 1; + break; + case COLOR_CODE_18BIT_CONFIG1: + case COLOR_CODE_18BIT_CONFIG2: + mipi_dsih_hal_dpi_18_loosely_packet_en(instance, video_params->is_18_loosely); + bytes_per_pixel_x100 = 225; + if (!video_params->is_18_loosely) + { /* 18bits per pixel and NOT loosely, packets should be multiples of 4 */ + video_size_step = 4; + /* round up active H pixels to a multiple of 4 */ + for (; (video_size % 4) != 0; video_size++) + { + ; + } + } + else + { + video_size_step = 1; + } + break; + case COLOR_CODE_24BIT: + bytes_per_pixel_x100 = 300; + video_size_step = 1; + break; + case COLOR_CODE_20BIT_YCC422_LOOSELY: + bytes_per_pixel_x100 = 250; + video_size_step = 2; + /* round up active H pixels to a multiple of 2 */ + if ((video_size % 2) != 0) + { + video_size += 1; + } + break; + case COLOR_CODE_24BIT_YCC422: + bytes_per_pixel_x100 = 300; + video_size_step = 2; + /* round up active H pixels to a multiple of 2 */ + if ((video_size % 2) != 0) + { + video_size += 1; + } + break; + case COLOR_CODE_16BIT_YCC422: + bytes_per_pixel_x100 = 200; + video_size_step = 2; + /* round up active H pixels to a multiple of 2 */ + if ((video_size % 2) != 0) + { + video_size += 1; + } + break; + case COLOR_CODE_30BIT: + bytes_per_pixel_x100 = 375; + video_size_step = 2; + break; + case COLOR_CODE_36BIT: + bytes_per_pixel_x100 = 450; + video_size_step = 2; + break; + case COLOR_CODE_12BIT_YCC420: + bytes_per_pixel_x100 = 150; + video_size_step = 2; + /* round up active H pixels to a multiple of 2 */ + if ((video_size % 2) != 0) + { + video_size += 1; + } + break; + default: + if (instance->log_error != 0) + { + instance->log_error("sprdfb: invalid color coding"); + } + err_code = ERR_DSI_COLOR_CODING; + break; + } + if (err_code == OK) + { + err_code = mipi_dsih_hal_dpi_color_coding(instance, video_params->color_coding); + } + if (err_code != OK) + { + return err_code; + } + mipi_dsih_hal_dpi_video_mode_type(instance, video_params->video_mode); + mipi_dsih_hal_dpi_hline(instance, (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR)); + mipi_dsih_hal_dpi_hbp(instance, ((video_params->h_back_porch_pixels * ratio_clock_xPF) / PRECISION_FACTOR)); + mipi_dsih_hal_dpi_hsa(instance, ((video_params->h_sync_pixels * ratio_clock_xPF) / PRECISION_FACTOR)); + mipi_dsih_hal_dpi_vactive(instance, video_params->v_active_lines); + mipi_dsih_hal_dpi_vfp(instance, video_params->v_total_lines - (video_params->v_back_porch_lines + video_params->v_sync_lines + video_params->v_active_lines)); + mipi_dsih_hal_dpi_vbp(instance, video_params->v_back_porch_lines); + mipi_dsih_hal_dpi_vsync(instance, video_params->v_sync_lines); + mipi_dsih_hal_dpi_hsync_pol(instance, !video_params->h_polarity); + mipi_dsih_hal_dpi_vsync_pol(instance, !video_params->v_polarity); + mipi_dsih_hal_dpi_dataen_pol(instance, !video_params->data_en_polarity); + /* HS timeout */ + hs_timeout = ((video_params->h_total_pixels * video_params->v_active_lines) + (DSIH_PIXEL_TOLERANCE * bytes_per_pixel_x100) / 100); + for (counter = 0x80; (counter < hs_timeout) && (counter > 2); counter--) + { + if ((hs_timeout % counter) == 0) + { + mipi_dsih_hal_timeout_clock_division(instance, counter); + mipi_dsih_hal_lp_rx_timeout(instance, (uint16_t)(hs_timeout / counter)); + mipi_dsih_hal_hs_tx_timeout(instance, (uint16_t)(hs_timeout / counter)); + break; + } + } + /* TX_ESC_CLOCK_DIV must be less than 20000KHz */ + mipi_dsih_hal_tx_escape_division(instance, 4); //6 //Jessia + /* video packetisation */ + if (video_params->video_mode == VIDEO_BURST_WITH_SYNC_PULSES) + { /* BURST */ + mipi_dsih_hal_dpi_null_packet_en(instance, 0); + mipi_dsih_hal_dpi_multi_packet_en(instance, 0); + err_code = mipi_dsih_hal_dpi_null_packet_size(instance, 0); + err_code = err_code? err_code: mipi_dsih_hal_dpi_chunks_no(instance, 1); + err_code = err_code? err_code: mipi_dsih_hal_dpi_video_packet_size(instance, video_size); + if (err_code != OK) + { + return err_code; + } + /* BURST by default, returns to LP during ALL empty periods - energy saving */ + mipi_dsih_hal_dpi_lp_during_hfp(instance, 1); +#if defined(CONFIG_FB_SCX35) && defined(CONFIG_FB_LCD_SSD2075_MIPI) + mipi_dsih_hal_dpi_lp_during_hbp(instance, 0);//forbit return to lp during hbp +#else + mipi_dsih_hal_dpi_lp_during_hbp(instance, 1); +#endif + mipi_dsih_hal_dpi_lp_during_vactive(instance, 1); + mipi_dsih_hal_dpi_lp_during_vfp(instance, 1); + mipi_dsih_hal_dpi_lp_during_vbp(instance, 1); + mipi_dsih_hal_dpi_lp_during_vsync(instance, 1); +#if DEBUG + /* D E B U G */ + if (instance->log_info != 0) + { + instance->log_info("sprdfb: burst video"); + instance->log_info("sprdfb: h line time %ld", (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR)); + instance->log_info("sprdfb: video_size %ld", video_size); + } +#endif + } + else + { /* non burst transmission */ + null_packet_size = 0; + /* bytes to be sent - first as one chunk */ + bytes_per_chunk = (bytes_per_pixel_x100 * video_params->h_active_pixels) / 100 + VIDEO_PACKET_OVERHEAD; + /* bytes being received through the DPI interface per byte clock cycle */ + total_bytes = (ratio_clock_xPF * video_params->no_of_lanes * (video_params->h_total_pixels - video_params->h_back_porch_pixels - video_params->h_sync_pixels)) / PRECISION_FACTOR; + /* check if the in pixels actually fit on the DSI link */ + if (total_bytes >= bytes_per_chunk) + { + chunk_overhead = total_bytes - bytes_per_chunk; + /* overhead higher than 1 -> enable multi packets */ + if (chunk_overhead > 1) + { /* MULTI packets */ + for (video_size = video_size_step; video_size < video_params->h_active_pixels; video_size += video_size_step) + { /* determine no of chunks */ + if ((((video_params->h_active_pixels * PRECISION_FACTOR) / video_size) % PRECISION_FACTOR) == 0) + { + no_of_chunks = video_params->h_active_pixels / video_size; + bytes_per_chunk = (bytes_per_pixel_x100 * video_size) / 100 + VIDEO_PACKET_OVERHEAD; + if (total_bytes >= (bytes_per_chunk * no_of_chunks)) + { + bytes_left = total_bytes - (bytes_per_chunk * no_of_chunks); + break; + } + } + } + /* prevent overflow (unsigned - unsigned) */ + if (bytes_left > (NULL_PACKET_OVERHEAD * no_of_chunks)) + { + null_packet_size = (bytes_left - (NULL_PACKET_OVERHEAD * no_of_chunks)) / no_of_chunks; + if (null_packet_size > MAX_NULL_SIZE) + { /* avoid register overflow */ + null_packet_size = MAX_NULL_SIZE; + } + } + } + else + { /* no multi packets */ + no_of_chunks = 1; +#if DEBUG + /* D E B U G */ + if (instance->log_info != 0) + { + instance->log_info("sprdfb: no multi no null video"); + instance->log_info("sprdfb: h line time %ld", (uint16_t)((video_params->h_total_pixels * ratio_clock_xPF) / PRECISION_FACTOR)); + instance->log_info("sprdfb: video_size %ld", video_size); + } + /************************/ +#endif + /* video size must be a multiple of 4 when not 18 loosely */ + for (video_size = video_params->h_active_pixels; (video_size % video_size_step) != 0; video_size++) + { + ; + } + } + } + else + { + instance->log_error("sprdfb: resolution cannot be sent to display through current settings"); + err_code = ERR_DSI_OVERFLOW; + } + } + err_code = err_code? err_code: mipi_dsih_hal_dpi_chunks_no(instance, no_of_chunks); + err_code = err_code? err_code: mipi_dsih_hal_dpi_video_packet_size(instance, video_size); + err_code = err_code? err_code: mipi_dsih_hal_dpi_null_packet_size(instance, null_packet_size); + mipi_dsih_hal_dpi_null_packet_en(instance, null_packet_size > 0? 1: 0); + mipi_dsih_hal_dpi_multi_packet_en(instance, (no_of_chunks > 1)? 1: 0); +#if DEBUG + /* D E B U G */ + if (instance->log_info != 0) + { + instance->log_info("sprdfb: total_bytes %d", total_bytes); + instance->log_info("sprdfb: bytes_per_chunk %d", bytes_per_chunk); + instance->log_info("sprdfb: bytes left %d", bytes_left); + instance->log_info("sprdfb: null packets %d", null_packet_size); + instance->log_info("sprdfb: chunks %ld", no_of_chunks); + instance->log_info("sprdfb: video_size %ld", video_size); + } + /************************/ +#endif + mipi_dsih_hal_dpi_video_vc(instance, video_params->virtual_channel); + mipi_dsih_dphy_no_of_lanes(&(instance->phy_instance), video_params->no_of_lanes); + /* enable high speed clock */ + //mipi_dsih_dphy_enable_hs_clk(&(instance->phy_instance), 1);//jessica, panel not init yet, could not set to hs, or result in err to some panel + return err_code; +} +/** + * Send a DCS write command + * It sends the User Command Set commands listed in the DCS specification and + * not the Manufacturer Command Set. To send the Manufacturer Commands use the + * packet on the generic packets sending function + * function sets the packet data type automatically + * @param instance pointer to structure holding the DSI Host core information + * @param vc destination virtual channel + * @param params byte-addressed array of command parameters, including the + * command itself + * @param param_length length of the above array + * @return error code + * @note this function has an active delay to wait for the buffer to clear. + * The delay is limited to DSIH_FIFO_ACTIVE_WAIT x register access time + */ +dsih_error_t mipi_dsih_dcs_wr_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length) +{ + uint8_t packet_type = 0; +// int i = 0; + if (params == 0) + { + return ERR_DSI_OUT_OF_BOUND; + } +#if 0 + if (param_length > 2) + { + i = 2; + } + switch (params[i]) + { + case 0x39: + case 0x38: + case 0x34: + case 0x29: + case 0x28: + case 0x21: + case 0x20: + case 0x13: + case 0x12: + case 0x11: + case 0x10: + case 0x01: + case 0x00: + packet_type = 0x05; /* DCS short write no param */ + break; + case 0x3A: + case 0x36: + case 0x35: + case 0x26: + packet_type = 0x15; /* DCS short write 1 param */ + break; + case 0x44: + case 0x3C: + case 0x37: + case 0x33: + case 0x30: + case 0x2D: + case 0x2C: + case 0x2B: + case 0x2A: + packet_type = 0x39; /* DCS long write/write_LUT command packet */ + break; + default: + if (instance->log_error != 0) + { + instance->log_error("invalid DCS command"); + } + return ERR_DSI_INVALID_COMMAND; + } +#else + switch(param_length) + { + case 1: + packet_type = 0x05; /* DCS short write no param */ + break; + case 2: + packet_type = 0x15; /* DCS short write 1 param */ + break; + default: + packet_type = 0x39; /* DCS long write/write_LUT command packet */ + break; + } +#endif + return mipi_dsih_gen_wr_packet(instance, vc, packet_type, params, param_length); +} +/** + * Enable command mode + * - This function shall be explicitly called before commands are send if they + * are to be sent in command mode and not interlaced with video + * - If video mode is ON, it will be turned off automatically + * @param instance pointer to structure holding the DSI Host core information + * @param en enable/disable + */ +void mipi_dsih_cmd_mode(dsih_ctrl_t * instance, int en) +{ + if(0 == instance) + { + return; + } + + if (instance->status == INITIALIZED) + { + mipi_dsih_hal_gen_cmd_mode_en(instance, en); + return; + } + if (instance->log_error != 0) + { + instance->log_error("sprdfb: [mipi_dsih_cmd_mode] invalid instance"); + } + +} +/** + * Enable video mode + * - If command mode is ON, it will be turned off automatically + * @param instance pointer to structure holding the DSI Host core information + * @param en enable/disable + */ +void mipi_dsih_video_mode(dsih_ctrl_t * instance, int en) +{ + if(0 == instance) + { + return; + } + + if (instance->status == INITIALIZED) + { + mipi_dsih_hal_dpi_video_mode_en(instance, en); + return; + } + if (instance->log_error != 0) + { + instance->log_error("sprdfb: [mipi_dsih_video_mode] invalid instance"); + } + +} + +/** + * Get the current active mode + * - 1 command mode + * - 2 DPI video mode + */ +int mipi_dsih_active_mode(dsih_ctrl_t * instance) +{ + if (mipi_dsih_hal_gen_is_cmd_mode(instance)) + { + return 1; + } + else if (mipi_dsih_hal_dpi_is_video_mode(instance)) + { + return 2; + } + return 0; +} +/** + * Send a generic write command + * @param instance pointer to structure holding the DSI Host core information + * @param vc destination virtual channel + * @param params byte-addressed array of command parameters + * @param param_length length of the above array + * @return error code + * @note this function has an active delay to wait for the buffer to clear. + * The delay is limited to DSIH_FIFO_ACTIVE_WAIT x register access time + */ +dsih_error_t mipi_dsih_gen_wr_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length) +{ + uint8_t data_type = 0; + switch(param_length) + { + case 0: + data_type = 0x03; + break; + case 1: + data_type = 0x13; + break; + case 2: + data_type = 0x23; + break; + default: + data_type = 0x29; + break; + } + return mipi_dsih_gen_wr_packet(instance, vc, data_type, params, param_length); +} +/** + * Send a packet on the generic interface + * @param instance pointer to structure holding the DSI Host core information + * @param vc destination virtual channel + * @param data_type type of command, inserted in first byte of header + * @param params byte array of command parameters + * @param param_length length of the above array + * @return error code + * @note this function has an active delay to wait for the buffer to clear. + * The delay is limited to: + * (param_length / 4) x DSIH_FIFO_ACTIVE_WAIT x register access time + * @note the controller restricts the sending of . + * This function will not be able to send Null and Blanking packets due to + * controller restriction + */ +dsih_error_t mipi_dsih_gen_wr_packet(dsih_ctrl_t * instance, uint8_t vc, uint8_t data_type, uint8_t* params, uint16_t param_length) +{ + dsih_error_t err_code = OK; + /* active delay iterator */ + int timeout = 0; + /* iterators */ + int i = 0; + int j = 0; + /* holds padding bytes needed */ + int compliment_counter = 0; + uint8_t* payload = 0; + /* temporary variable to arrange bytes into words */ + uint32_t temp = 0; + uint16_t word_count = 0; + if (instance == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (instance->status != INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + if ((params == 0) && (param_length != 0)) /* pointer NULL */ + { + return ERR_DSI_OUT_OF_BOUND; + } + if (param_length > 2) + { /* long packet - write word count to header, and the rest to payload */ + payload = params + (2 * sizeof(params[0])); + word_count = (params[1] << 8) | params[0]; + if ((param_length - 2) < word_count) + { + if (instance->log_error != 0) + { + instance->log_error("sprdfb: sent > input payload. complemented with zeroes"); + } + compliment_counter = (param_length - 2) - word_count; + } + else if ((param_length - 2) > word_count) + { + if (instance->log_error != 0) + { + instance->log_error("sprdfb: Overflow - input > sent. payload truncated"); + } + } + for (i = 0; i < (param_length - 2); i += j) + { + temp = 0; + for (j = 0; (j < 4) && ((j + i) < (param_length - 2)); j++) + { /* temp = (payload[i + 3] << 24) | (payload[i + 2] << 16) | (payload[i + 1] << 8) | payload[i]; */ + temp |= payload[i + j] << (j * 8); + } + /* check if payload Tx fifo is not full */ + for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++) + { + if (!mipi_dsih_hal_gen_packet_payload(instance, temp)) + { + break; + } + } + if (!(timeout < DSIH_FIFO_ACTIVE_WAIT)) + { + return ERR_DSI_TIMEOUT; + } + } + /* if word count entered by the user more than actual parameters received + * fill with zeroes - a fail safe mechanism, otherwise controller will + * want to send data from an empty buffer */ + for (i = 0; i < compliment_counter; i++) + { + /* check if payload Tx fifo is not full */ + for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++) + { + if (!mipi_dsih_hal_gen_packet_payload(instance, 0x00)) + { + break; + } + } + if (!(timeout < DSIH_FIFO_ACTIVE_WAIT)) + { + return ERR_DSI_TIMEOUT; + } + } + } + for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++) + { + /* check if payload Tx fifo is not full */ + if (!mipi_dsih_hal_gen_cmd_fifo_full(instance)) + { + if (param_length == 0) + { + err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, 0x0, 0x0); + } + else if (param_length == 1) + { + err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, 0x0, params[0]); + } + else + { + err_code |= mipi_dsih_hal_gen_packet_header(instance, vc, data_type, params[1], params[0]); + } + break; + } + } + if (!(timeout < DSIH_FIFO_ACTIVE_WAIT)) + { + err_code = ERR_DSI_TIMEOUT; + } + return err_code; +} +/** + * Send a DCS READ command to peripheral + * function sets the packet data type automatically + * @param instance pointer to structure holding the DSI Host core information + * @param vc destination virtual channel + * @param command DCS code + * @param bytes_to_read no of bytes to read (expected to arrive at buffer) + * @param read_buffer pointer to 8-bit array to hold the read buffer words + * return read_buffer_length + * @note this function has an active delay to wait for the buffer to clear. + * The delay is limited to 2 x DSIH_FIFO_ACTIVE_WAIT + * (waiting for command buffer, and waiting for receiving) + * @note this function will enable BTA + */ +uint16_t mipi_dsih_dcs_rd_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t command, uint8_t bytes_to_read, uint8_t* read_buffer) +{ + if (instance == 0) + { + return 0; + } + if (instance->status != INITIALIZED) + { + return 0; + } + switch (command) + { + case 0xA8: + case 0xA1: + case 0x45: + case 0x3E: + case 0x2E: + case 0x0F: + case 0x0E: + case 0x0D: + case 0x0C: + case 0x0B: + case 0x0A: + case 0x08: + case 0x07: + case 0x06: + /* COMMAND_TYPE 0x06 - DCS Read no params refer to DSI spec p.47 */ + return mipi_dsih_gen_rd_packet(instance, vc, 0x06, 0x0, command, bytes_to_read, read_buffer); + default: + if (instance->log_error != 0) + { + instance->log_error("sprdfb: invalid DCS command"); + } + return 0; + } + return 0; +} +/** + * Send Generic READ command to peripheral + * - function sets the packet data type automatically + * @param instance pointer to structure holding the DSI Host core information + * @param vc destination virtual channel + * @param params byte array of command parameters + * @param param_length length of the above array + * @param bytes_to_read no of bytes to read (expected to arrive at buffer) + * @param read_buffer pointer to 8-bit array to hold the read buffer words + * return read_buffer_length + * @note this function has an active delay to wait for the buffer to clear. + * The delay is limited to 2 x DSIH_FIFO_ACTIVE_WAIT + * (waiting for command buffer, and waiting for receiving) + * @note this function will enable BTA + */ +uint16_t mipi_dsih_gen_rd_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length, uint8_t bytes_to_read, uint8_t* read_buffer) +{ + uint8_t data_type = 0; + if (instance == 0) + { + return 0; + } + if (instance->status != INITIALIZED) + { + return 0; + } + switch(param_length) + { + case 0: + data_type = 0x04; + return mipi_dsih_gen_rd_packet(instance, vc, data_type, 0x00, 0x00, bytes_to_read, read_buffer); + case 1: + data_type = 0x14; + return mipi_dsih_gen_rd_packet(instance, vc, data_type, 0x00, params[0], bytes_to_read, read_buffer); + case 2: + data_type = 0x24; + return mipi_dsih_gen_rd_packet(instance, vc, data_type, params[1], params[0], bytes_to_read, read_buffer); + default: + return 0; + } +} +/** + * Send READ packet to peripheral using the generic interface + * This will force command mode and stop video mode (because of BTA) + * @param instance pointer to structure holding the DSI Host core information + * @param vc destination virtual channel + * @param data_type generic command type + * @param lsb_byte first command parameter + * @param msb_byte second command parameter + * @param bytes_to_read no of bytes to read (expected to arrive at buffer) + * @param read_buffer pointer to 8-bit array to hold the read buffer words + * return read_buffer_length + * @note this function has an active delay to wait for the buffer to clear. + * The delay is limited to 2 x DSIH_FIFO_ACTIVE_WAIT + * (waiting for command buffer, and waiting for receiving) + * @note this function will enable BTA + */ +uint16_t mipi_dsih_gen_rd_packet(dsih_ctrl_t * instance, uint8_t vc, uint8_t data_type, uint8_t msb_byte, uint8_t lsb_byte, uint8_t bytes_to_read, uint8_t* read_buffer) +{ + dsih_error_t err_code = OK; + int timeout = 0; + int counter = 0; + int i = 0; + int last_count = 0; + uint32_t temp[1] = {0}; + if (instance == 0) + { + return 0; + } + if (instance->status != INITIALIZED) + { + return 0; + } + if (bytes_to_read < 1) + { + return 0; + } + if (read_buffer == 0) + { + return 0; + } +#ifndef FB_CHECK_ESD_IN_VFP + /* make sure command mode is on */ + mipi_dsih_cmd_mode(instance, 1); +#endif + /* make sure receiving is enabled */ + mipi_dsih_hal_bta_en(instance, 1); + /* listen to the same virtual channel as the one sent to */ + mipi_dsih_hal_gen_rd_vc(instance, vc); + for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++) + { /* check if payload Tx fifo is not full */ + if (!mipi_dsih_hal_gen_cmd_fifo_full(instance)) + { + mipi_dsih_hal_gen_packet_header(instance, vc, data_type, msb_byte, lsb_byte); + break; + } + } + if (!(timeout < DSIH_FIFO_ACTIVE_WAIT)) + { + if (instance->log_error != 0) + { + instance->log_error("sprdfb: tx rd command timed out"); + } + return 0; + } + /* loop for the number of words to be read */ + for (timeout = 0; timeout < DSIH_FIFO_ACTIVE_WAIT; timeout++) + { /* check if command transaction is done */ + if (!mipi_dsih_hal_gen_rd_cmd_busy(instance)) + { + if (!mipi_dsih_hal_gen_read_fifo_empty(instance)) + { + for (counter = 0; (!mipi_dsih_hal_gen_read_fifo_empty(instance)); counter += 4) + { + err_code = mipi_dsih_hal_gen_read_payload(instance, temp); + if (err_code) + { + return 0; + } + if (counter < bytes_to_read) + { + for (i = 0; i < 4; i++) + { + if ((counter + i) < bytes_to_read) + { + /* put 32 bit temp in 4 bytes of buffer passed by user*/ + read_buffer[counter + i] = (uint8_t)(temp[0] >> (i * 8)); + last_count = i + counter; + } + else + { + if ((uint8_t)(temp[0] >> (i * 8)) != 0x00) + { + last_count = i + counter; + } + } + } + } + else + { + last_count = counter; + for (i = 0; i < 4; i++) + { + if ((uint8_t)(temp[0] >> (i * 8)) != 0x00) + { + last_count = i + counter; + } + } + } + } + return last_count + 1; + } +#ifdef FB_CHECK_ESD_IN_VFP + else if(timeout == (DSIH_FIFO_ACTIVE_WAIT - 1))//else +#else + else +#endif + { + if (instance->log_error != 0) + { + instance->log_error("sprdfb: rx buffer empty"); + } + return 0; + } + } +#ifdef FB_CHECK_ESD_IN_VFP + udelay(5); +#endif + } + if (instance->log_error != 0) + { + instance->log_error("sprdfb: rx command timed out"); + } + return 0; +} +/** + * Dump values stored in the DSI host core registers + * @param instance pointer to structure holding the DSI Host core information + * @param all whether to dump all the registers, no register_config array need + * be provided if dump is to standard IO + * @param config array of register_config_t type where addresses and values are + * stored + * @param config_length the length of the config array + * @return the number of the registers that were read + */ +uint32_t mipi_dsih_dump_register_configuration(dsih_ctrl_t * instance, int all, register_config_t *config, uint16_t config_length) +{ + uint32_t current0 = 0; + uint16_t count = 0; + if (instance == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (instance->status != INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (all) + { /* dump all registers */ + for (current0 = R_DSI_HOST_VERSION; current0 <= R_DSI_HOST_PHY_TMR_LPCLK_CFG; count++, current0 += (R_DSI_HOST_PWR_UP - R_DSI_HOST_VERSION)) + { + if ((config_length == 0) || (config == 0) || count >= config_length) + { /* no place to write - write to STD IO */ + if (instance->log_info != 0) + { + instance->log_info("sprdfb: DSI 0x%lX:0x%lX", current0, mipi_dsih_read_word(instance, current0)); + } + } + else + { + config[count].addr = current0; + config[count].data = mipi_dsih_read_word(instance, current0); + } + } + } + else + { + if(config == 0) + { + if (instance->log_error != 0) + { + instance->log_error("sprdfb: invalid buffer"); + } + } + else + { + for (count = 0; count < config_length; count++) + { + config[count].data = mipi_dsih_read_word(instance, config[count].addr); + } + } + } + return count; +} +/** + * Write values to DSI host core registers + * @param instance pointer to structure holding the DSI Host core information + * @param config array of register_config_t type where register addresses and + * their new values are stored + * @param config_length the length of the config array + * @return the number of the registers that were written to + */ +uint32_t mipi_dsih_write_register_configuration(dsih_ctrl_t * instance, register_config_t *config, uint16_t config_length) +{ + uint16_t count = 0; + if (instance == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (instance->status != INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + for (count = 0; count < config_length; count++) + { + mipi_dsih_write_word(instance, config[count].addr, config[count].data); + } + return count; +} +/** + * Register a handler for a specific event + * - The handler will be called when this specific event occurs + * @param instance pointer to structure holding the DSI Host core information + * @param event enum + * @param handler call back to handler function to handle the event + * @return error code + */ +dsih_error_t mipi_dsih_register_event(dsih_ctrl_t * instance, dsih_event_t event, void (*handler)(dsih_ctrl_t *, void *)) +{ + uint32_t mask = 1; + uint32_t temp = 0; + if (event >= DSI_MAX_EVENT) + { + return ERR_DSI_INVALID_EVENT; + } + if (handler == 0) + { + return ERR_DSI_INVALID_HANDLE; + } + if (instance == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (instance->status != INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + instance->event_registry[event] = handler; + if (event < HS_CONTENTION) + { + temp = mipi_dsih_hal_int_get_mask_0(instance, 0xffffffff); + temp &= ~(mask << event); + temp |= (0 & mask) << event; + mipi_dsih_hal_int_mask_0(instance, temp); + } + else + { + temp = mipi_dsih_hal_int_get_mask_1(instance, 0xffffffff); + temp &= ~(mask << (event - HS_CONTENTION)); + temp |= (0 & mask) << (event - HS_CONTENTION); + mipi_dsih_hal_int_mask_1(instance, temp); + if (event == RX_CRC_ERR) + { /* automatically enable CRC reporting */ + mipi_dsih_hal_gen_crc_rx_en(instance, 1); + } + } + return OK; +} +/** + * Clear an already registered event + * - Callback of the handler will be removed + * @param instance pointer to structure holding the DSI Host core information + * @param event enum + * @return error code + */ +dsih_error_t mipi_dsih_unregister_event(dsih_ctrl_t * instance, dsih_event_t event) +{ + uint32_t mask = 1; + uint32_t temp = 0; + if (event >= DSI_MAX_EVENT) + { + return ERR_DSI_INVALID_EVENT; + } + if (instance == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (instance->status != INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + instance->event_registry[event] = 0; + if (event < HS_CONTENTION) + { + temp = mipi_dsih_hal_int_get_mask_0(instance, 0xffffffff); + temp &= ~(mask << event); + temp |= (1 & mask) << event; + mipi_dsih_hal_int_mask_0(instance, temp); + } + else + { + temp = mipi_dsih_hal_int_get_mask_1(instance, 0xffffffff); + temp &= ~(mask << (event - HS_CONTENTION)); + temp |= (1 & mask) << (event - HS_CONTENTION); + mipi_dsih_hal_int_mask_1(instance, temp); + if (event == RX_CRC_ERR) + { /* automatically disable CRC reporting */ + mipi_dsih_hal_gen_crc_rx_en(instance, 0); + } + } + return OK; +} +/** + * Clear all registered events at once + * @param instance pointer to structure holding the DSI Host core information + * @return error code + */ +dsih_error_t mipi_dsih_unregister_all_events(dsih_ctrl_t * instance) +{ + int i = 0; + if (instance == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (instance->status != INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + for (i = 0; i < DSI_MAX_EVENT; i++) + { + instance->event_registry[i] = 0; + } + mipi_dsih_hal_int_mask_0(instance, 0xffffff); + mipi_dsih_hal_int_mask_1(instance, 0xffffff); + /* automatically disable CRC reporting */ + mipi_dsih_hal_gen_crc_rx_en(instance, 0); + return OK; +} +/** + * This event handler shall be called upon receiving any event + * it will call the specific callback (handler) registered for the invoking + * event. Registration is done beforehand using mipi_dsih_register_event + * its signature is void * so it could be OS agnostic (for it to be + * registered in any OS/Interrupt controller) + * @param param pointer to structure holding the DSI Host core information + * @note This function must be registered with the DSI IRQs + */ +void mipi_dsih_event_handler(void * param) +{ + dsih_ctrl_t * instance = (dsih_ctrl_t *)(param); + uint8_t i = 0; + uint32_t status_0; + uint32_t status_1; + + if (instance == 0) + { + return; + } + + status_0 = mipi_dsih_hal_int_status_0(instance, 0xffffffff); + status_1 = mipi_dsih_hal_int_status_1(instance, 0xffffffff); + + for (i = 0; i < DSI_MAX_EVENT; i++) + { + if (instance->event_registry[i] != 0) + { + if (i < HS_CONTENTION) + { + if ((status_0 & (1 << i)) != 0) + { + instance->event_registry[i](instance, &i); + } + } + else + { + if ((status_1 & (1 << (i - HS_CONTENTION))) != 0) + { + instance->event_registry[i](instance, &i); + } + } + } + } +} +/** + * Reset the DSI Host controller + * - Sends a pulse to the shut down register + * @param instance pointer to structure holding the DSI Host core information + */ +void mipi_dsih_reset_controller(dsih_ctrl_t * instance) +{ + mipi_dsih_hal_power(instance, 0); + mipi_dsih_hal_power(instance, 1); +} +/** + * Shut down the DSI Host controller + * @param instance pointer to structure holding the DSI Host core information + * @param shutdown (1) power up (0) + */ +void mipi_dsih_shutdown_controller(dsih_ctrl_t * instance, int shutdown) +{ + mipi_dsih_hal_power(instance, !shutdown); +} +/** + * Reset the PHY module being controlled by the DSI Host controller + * - Sends a pulse to the PPI reset signal + * @param instance pointer to structure holding the DSI Host core information + */ +void mipi_dsih_reset_phy(dsih_ctrl_t * instance) +{ + mipi_dsih_dphy_reset(&(instance->phy_instance), 0); + mipi_dsih_dphy_reset(&(instance->phy_instance), 1); +} +/** + * Shut down the PHY module being controlled by the DSI Host controller + * @param instance pointer to structure holding the DSI Host core information + * @param shutdown (1) power up (0) + */ +void mipi_dsih_shutdown_phy(dsih_ctrl_t * instance, int shutdown) +{ + mipi_dsih_dphy_shutdown(&(instance->phy_instance), !shutdown); +} + +/* +sprd Aoke added for power saving while suspend +*/ +void mipi_dsih_ulps_mode(dsih_ctrl_t * instance, int en) +{ + mipi_dsih_dphy_ulps_data_lanes(&(instance->phy_instance),en); + mipi_dsih_dphy_ulps_clk_lane(&(instance->phy_instance),en); +} +/** + * Configure the eDPI interface + * - Programs the controller to receive pixels on the DPI interface and send them + * as commands (write memory start and write memory continue) instead of a + * video stream. + * @param instance pointer to structure holding the DSI Host core information + * @param video_params pointer to the command mode video parameters context + * @param send_setup_packets whether to send the setup packets from given info. These are: 1 - set pixel format; 2 - set column address; 3 - set page address + * @return error code + */ +dsih_error_t mipi_dsih_edpi_video(dsih_ctrl_t * instance, dsih_cmd_mode_video_t *video_params, int send_setup_packets) +{ + dsih_error_t err_code = OK; + uint8_t buf[7] = {0}; + uint32_t bytes_per_pixel_x100 = 0; + mipi_dsih_hal_dpi_video_vc(instance, video_params->virtual_channel); + mipi_dsih_cmd_mode(instance, 1); + err_code = mipi_dsih_hal_dpi_color_coding(instance, video_params->color_coding); + /* define whether write memory commands will be sent in LP or HS */ + err_code = err_code? err_code: mipi_dsih_hal_dcs_wr_tx_type(instance, 3, video_params->lp); /* long packet*/ + if (send_setup_packets) + { + /* define pixel packing format - 1 param */ + buf[0] = 0x3A; + /* colour depth: table 6 DCS spec. 3:1| 8:2| 12:3| 16:5| 18:6| 24:7*/ + switch (video_params->color_coding) + { + case 0: + case 1: + case 2: + buf[1] = 5; + break; + case 3: + case 4: + buf[1] = 6; + break; + default: + buf[1] = 7; + break; + } + err_code = err_code? err_code: mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 2); + if (err_code) + { + instance->log_error("sprdfb: error setting up command video - colour depth"); + } + /* set column address (left to right) - 4 param */ + buf[0] = 0x05; /* cmd length */ + buf[1] = 0x00; + buf[2] = 0x2A; /* cmd opcode */ + buf[3] = (uint8_t)(video_params->h_start >> 8); /* payload start */ + buf[4] = (uint8_t)(video_params->h_start); + buf[5] = (uint8_t)(video_params->h_active_pixels >> 8); + buf[6] = (uint8_t)(video_params->h_active_pixels); + err_code = err_code? err_code: mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 7); + if (err_code) + { + instance->log_error("sprdfb: error setting up command video - set column address"); + } + /* set page address (top to bottom) 4 - param*/ + buf[0] = 0x05; /* cmd length */ + buf[1] = 0x00; + buf[2] = 0x2B; /* cmd opcode */ + buf[3] = (uint8_t)(video_params->v_start >> 8); /* payload start */ + buf[4] = (uint8_t)(video_params->v_start); + buf[5] = (uint8_t)(video_params->v_active_lines >> 8); + buf[6] = (uint8_t)(video_params->v_active_lines); + err_code = err_code? err_code: mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 7); + if (err_code) + { + instance->log_error("sprdfb: error setting up command video - set page address"); + } + } + switch (video_params->color_coding) + { + case COLOR_CODE_16BIT_CONFIG1: + case COLOR_CODE_16BIT_CONFIG2: + case COLOR_CODE_16BIT_CONFIG3: + bytes_per_pixel_x100 = 200; + break; + case COLOR_CODE_18BIT_CONFIG1: + case COLOR_CODE_18BIT_CONFIG2: + bytes_per_pixel_x100 = 225; + break; + case COLOR_CODE_24BIT: + bytes_per_pixel_x100 = 300; + break; + case COLOR_CODE_20BIT_YCC422_LOOSELY: + bytes_per_pixel_x100 = 250; + break; + case COLOR_CODE_24BIT_YCC422: + bytes_per_pixel_x100 = 300; + break; + case COLOR_CODE_16BIT_YCC422: + bytes_per_pixel_x100 = 200; + break; + case COLOR_CODE_30BIT: + bytes_per_pixel_x100 = 375; + break; + case COLOR_CODE_36BIT: + bytes_per_pixel_x100 = 450; + break; + case COLOR_CODE_12BIT_YCC420: + bytes_per_pixel_x100 = 150; + break; + default: + if (instance->log_error != 0) + { + instance->log_error("sprdfb: invalid color coding"); + } + err_code = ERR_DSI_COLOR_CODING; + break; + } + if (video_params->te) + { + mipi_dsih_hal_bta_en(instance, video_params->te); + /* enable tearing effect */ + mipi_dsih_tear_effect_ack(instance, video_params->te); + buf[0] = 0x35; + err_code = mipi_dsih_dcs_wr_cmd(instance, video_params->virtual_channel, buf, 1); + } + mipi_dsih_dphy_enable_hs_clk(&(instance->phy_instance), 1); + if ((((WORD_LENGTH * FIFO_DEPTH) * 100) / bytes_per_pixel_x100) > video_params->h_active_pixels) + { + mipi_dsih_hal_edpi_max_allowed_size(instance, video_params->h_active_pixels); + } + else + { + mipi_dsih_hal_edpi_max_allowed_size(instance, (((WORD_LENGTH * FIFO_DEPTH) * 100) / bytes_per_pixel_x100)); + } + return err_code; +} + +/* PRESP Time outs */ +/** + * Timeout for peripheral (for controller to stay still) after LP data + * transmission write requests + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the + * link still, after sending a low power write operation. This period is + * measured in cycles of lanebyteclk + */ +void mipi_dsih_presp_timeout_low_power_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + mipi_dsih_hal_presp_timeout_low_power_write(instance, no_of_byte_cycles); +} +/** + * Timeout for peripheral (for controller to stay still) after LP data + * transmission read requests + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the + * link still, after sending a low power read operation. This period is + * measured in cycles of lanebyteclk + */ +void mipi_dsih_presp_timeout_low_power_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + mipi_dsih_hal_presp_timeout_low_power_read(instance, no_of_byte_cycles); +} +/** + * Timeout for peripheral (for controller to stay still) after HS data + * transmission write requests + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the + * link still, after sending a high-speed write operation. This period is + * measured in cycles of lanebyteclk + */ +void mipi_dsih_presp_timeout_high_speed_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + mipi_dsih_hal_presp_timeout_high_speed_write(instance, no_of_byte_cycles); +} +/** + * Timeout for peripheral between HS data transmission read requests + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the + * link still, after sending a high-speed read operation. This period is + * measured in cycles of lanebyteclk + */ +void mipi_dsih_presp_timeout_high_speed_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + mipi_dsih_hal_presp_timeout_high_speed_read(instance, no_of_byte_cycles); +} +/** + * Timeout for peripheral (for controller to stay still) after bus turn around + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the + * link still, after sending a BTA operation. This period is + * measured in cycles of lanebyteclk + */ +void mipi_dsih_presp_timeout_bta(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + mipi_dsih_hal_presp_timeout_bta(instance, no_of_byte_cycles); +} +uint16_t mipi_dsih_check_dbi_fifos_state(dsih_ctrl_t * instance) +{ + uint16_t cnt = 0; + while( cnt < 5000 && mipi_dsih_read_word(instance, R_DSI_HOST_CMD_PKT_STATUS) != 0x15) + { + cnt ++; + } + return (mipi_dsih_read_word(instance, R_DSI_HOST_CMD_PKT_STATUS) != 0x15) ? -1 : 1; +} +uint16_t mipi_dsih_check_ulpm_mode(dsih_ctrl_t * instance) +{ + return (mipi_dsih_read_word(instance, R_DSI_HOST_PHY_STATUS) != 0x1528) ? -1 : 1; +} diff --git a/drivers/autotst/mipi_dsih_api.h b/drivers/autotst/mipi_dsih_api.h new file mode 100644 index 00000000..5208467a --- /dev/null +++ b/drivers/autotst/mipi_dsih_api.h @@ -0,0 +1,134 @@ +/** + * @file mipi_dsih_api.h + * + * Synopsys Inc. + * SG DWC PT02 + */ +/* + The Synopsys Software Driver and documentation (hereinafter "Software") + is an unsupported proprietary work of Synopsys, Inc. unless otherwise + expressly agreed to in writing between Synopsys and you. + + The Software IS NOT an item of Licensed Software or Licensed Product under + any End User Software License Agreement or Agreement for Licensed Product + with Synopsys or any supplement thereto. Permission is hereby granted, + free of charge, to any person obtaining a copy of this software annotated + with this license and the Software, to deal in the Software without + restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject + to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + */ +#ifndef MIPI_DSIH_API_H_ +#define MIPI_DSIH_API_H_ + +#include "mipi_dsih_local.h" + +/* general configuration functions */ + +dsih_error_t mipi_dsih_open(dsih_ctrl_t * instance); + +dsih_error_t mipi_dsih_close(dsih_ctrl_t * instance); + +void mipi_dsih_reset_controller(dsih_ctrl_t * instance); + +void mipi_dsih_shutdown_controller(dsih_ctrl_t * instance, int shutdown); + +void mipi_dsih_reset_phy(dsih_ctrl_t * instance); + +void mipi_dsih_shutdown_phy(dsih_ctrl_t * instance, int shutdown); + +void mipi_dsih_ulps_mode(dsih_ctrl_t * instance, int en);//Aoke add +/* packet handling */ + +dsih_error_t mipi_dsih_enable_rx(dsih_ctrl_t * instance, int enable); + +dsih_error_t mipi_dsih_peripheral_ack(dsih_ctrl_t * instance, int enable); + +dsih_error_t mipi_dsih_tear_effect_ack(dsih_ctrl_t * instance, int enable); + +dsih_error_t mipi_dsih_eotp_rx(dsih_ctrl_t * instance, int enable); + +dsih_error_t mipi_dsih_ecc_rx(dsih_ctrl_t * instance, int enable); + + +dsih_error_t mipi_dsih_eotp_tx(dsih_ctrl_t * instance, int enable); + +/* video mode functions */ + +dsih_error_t mipi_dsih_dpi_video(dsih_ctrl_t * instance, dsih_dpi_video_t * video_params); + +void mipi_dsih_allow_return_to_lp(dsih_ctrl_t * instance, int hfp, int hbp, int vactive, int vfp, int vbp, int vsync); + +void mipi_dsih_video_mode(dsih_ctrl_t * instance, int en); + +/* command mode functions */ + +dsih_error_t mipi_dsih_dcs_wr_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length); + +dsih_error_t mipi_dsih_gen_wr_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length); + +dsih_error_t mipi_dsih_gen_wr_packet(dsih_ctrl_t * instance, uint8_t vc, uint8_t data_type, uint8_t* params, uint16_t param_length); + +uint16_t mipi_dsih_dcs_rd_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t command, uint8_t bytes_to_read, uint8_t* read_buffer); + +uint16_t mipi_dsih_gen_rd_cmd(dsih_ctrl_t * instance, uint8_t vc, uint8_t* params, uint16_t param_length, uint8_t bytes_to_read, uint8_t* read_buffer); + +uint16_t mipi_dsih_gen_rd_packet(dsih_ctrl_t * instance, uint8_t vc, uint8_t data_type, uint8_t msb_byte, uint8_t lsb_byte, uint8_t bytes_to_read, uint8_t* read_buffer); + +void mipi_dsih_cmd_mode(dsih_ctrl_t * instance, int en); + +int mipi_dsih_active_mode(dsih_ctrl_t * instance); + +void mipi_dsih_dcs_cmd_lp_transmission(dsih_ctrl_t * instance, int long_write, int short_write, int short_read); + +void mipi_dsih_gen_cmd_lp_transmission(dsih_ctrl_t * instance, int long_write, int short_write, int short_read); + +dsih_error_t mipi_dsih_edpi_video(dsih_ctrl_t * instance, dsih_cmd_mode_video_t *video_params, int send_setup_packets); + +/* event handling functions */ + +dsih_error_t mipi_dsih_register_event(dsih_ctrl_t * instance, dsih_event_t event, void (*handler)(dsih_ctrl_t *, void *)); + +dsih_error_t mipi_dsih_unregister_event(dsih_ctrl_t * instance, dsih_event_t event); + +dsih_error_t mipi_dsih_unregister_all_events(dsih_ctrl_t * instance); + +void mipi_dsih_event_handler(void * param); + +/* PRESP Time outs */ +void mipi_dsih_presp_timeout_low_power_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); + +void mipi_dsih_presp_timeout_low_power_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); + +void mipi_dsih_presp_timeout_high_speed_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); + +void mipi_dsih_presp_timeout_high_speed_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); + +void mipi_dsih_presp_timeout_bta(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); + +/* read/write register functions */ +uint32_t mipi_dsih_dump_register_configuration(dsih_ctrl_t * instance, int all, register_config_t *config, uint16_t config_length); + +uint32_t mipi_dsih_write_register_configuration(dsih_ctrl_t * instance, register_config_t *config, uint16_t config_length); + +uint16_t mipi_dsih_check_dbi_fifos_state(dsih_ctrl_t * instance); + +uint16_t mipi_dsih_check_ulpm_mode(dsih_ctrl_t * instance); + +#endif /* MIPI_DSIH_API_H_ */ diff --git a/drivers/autotst/mipi_dsih_dphy.c b/drivers/autotst/mipi_dsih_dphy.c new file mode 100644 index 00000000..c137e9d5 --- /dev/null +++ b/drivers/autotst/mipi_dsih_dphy.c @@ -0,0 +1,1082 @@ +/** + * @file mipi_dsih_dphy.c + * @brief D-PHY driver + * + * Synopsys Inc. + * SG DWC PT02 + */ +#include "mipi_dsih_dphy.h" +#define PRECISION_FACTOR (1000) +/* Reference clock frequency divided by Input Frequency Division Ratio LIMITS */ +#define DPHY_DIV_UPPER_LIMIT (40000) +#ifdef GEN_2 +#define DPHY_DIV_LOWER_LIMIT (5000) +#else +#define DPHY_DIV_LOWER_LIMIT (1000) +#endif + +#if ((defined DWC_MIPI_DPHY_BIDIR_TSMC40LP) || (defined GEN_2)) +#define MIN_OUTPUT_FREQ (80) +#elif defined DPHY2Btql +#define MIN_OUTPUT_FREQ (200) +#undef GEN_2 +#endif + +/** + * Initialise D-PHY module and power up + * @param phy pointer to structure which holds information about the d-phy + * module + * @return error code + */ +dsih_error_t mipi_dsih_dphy_open(dphy_t * phy) +{ + if (phy == 0) + { + return ERR_DSI_PHY_INVALID; + } + else if ((phy->core_read_function == 0) || (phy->core_write_function == 0)) + { + return ERR_DSI_INVALID_IO; + } + else if (phy->status == INITIALIZED) + { + return ERR_DSI_PHY_INVALID; + } + phy->status = NOT_INITIALIZED; +#if 0 + mipi_dsih_dphy_reset(phy, 0); + mipi_dsih_dphy_stop_wait_time(phy, 0x1C); + mipi_dsih_dphy_no_of_lanes(phy, 1); + mipi_dsih_dphy_clock_en(phy, 1); + mipi_dsih_dphy_shutdown(phy, 1); + mipi_dsih_dphy_reset(phy, 1); +#endif + phy->status = INITIALIZED; + return OK; +} +/** + * Configure D-PHY and PLL module to desired operation mode + * @param phy pointer to structure which holds information about the d-phy + * module + * @param no_of_lanes active + * @param output_freq desired high speed frequency + * @return error code + */ + #ifdef GEN_2 +dsih_error_t mipi_dsih_dphy_configure(dphy_t * phy, uint8_t no_of_lanes, uint32_t output_freq) +{ + uint32_t loop_divider = 0; /* (M) */ + uint32_t input_divider = 1; /* (N) */ + uint8_t data[4]; /* maximum data for now are 4 bytes per test mode*/ + uint8_t no_of_bytes = 0; + uint8_t i = 0; + uint8_t n=0;/* iterator */ + uint8_t range = 0; /* ranges iterator */ + int flag = 0; + struct + { + uint32_t loop_div; /* upper limit of loop divider range */ + uint8_t cp_current; /* icpctrl */ + uint8_t lpf_resistor; /* lpfctrl */ + } + loop_bandwidth[] = + + { /* gen 2 associates the charge pump current and LPF resistor with the + output frequency ranges (and thus we simplify here to use the + counter/pointer of the following structure) */ + { 90, 0x02, 0x02}, { 100, 0x02, 0x02}, { 110, 0x02, 0x02}, + { 130, 0x02, 0x01}, { 140, 0x02, 0x01}, { 150, 0x02, 0x01}, + { 170, 0x09, 0x00}, { 180, 0x09, 0x01}, { 200, 0x09, 0x01}, + { 220, 0x09, 0x04}, { 240, 0x09, 0x04}, { 250, 0x09, 0x04}, + { 270, 0x06, 0x04}, { 300, 0x06, 0x04}, { 330, 0x09, 0x04}, + { 360, 0x09, 0x04}, { 400, 0x09, 0x04}, { 450, 0x06, 0x04}, + { 500, 0x06, 0x04}, { 550, 0x06, 0x04}, { 600, 0x06, 0x04}, + { 650, 0x0A, 0x04}, { 700, 0x0A, 0x04}, { 750, 0x0A, 0x04}, + { 800, 0x0A, 0x04}, { 850, 0x0A, 0x04}, { 900, 0x0A, 0x04}, + { 950, 0x0B, 0x08}, {1000, 0x0B, 0x08}, {1050, 0x0B, 0x08}, + {1100, 0x0B, 0x08}, {1150, 0x0B, 0x08}, {1200, 0x0B, 0x08}, + {1250, 0x0B, 0x08}, {1300, 0x0B, 0x08}, {1350, 0x0B, 0x08}, + {1400, 0x0B, 0x08}, {1450, 0x0B, 0x08}, {1500, 0x0B, 0x08} + }; + uint32_t delta = 0; + uint32_t tmp_loop_divider = 0; + unsigned step = 0; + + struct + { + uint32_t freq; /* upper margin of frequency range */ + uint8_t hs_freq; /* hsfreqrange */ + uint8_t vco_range; /* vcorange */ + } + ranges[] = + { + { 90, 0x00, 0x00}, { 100, 0x10, 0x00}, { 110, 0x20, 0x00}, + { 130, 0x01, 0x00}, { 140, 0x11, 0x00}, { 150, 0x21, 0x00}, + { 170, 0x02, 0x00}, { 180, 0x12, 0x00}, { 200, 0x22, 0x00}, + { 220, 0x03, 0x01}, { 240, 0x13, 0x01}, { 250, 0x23, 0x01}, + { 270, 0x04, 0x01}, { 300, 0x14, 0x01}, { 330, 0x05, 0x02}, + { 360, 0x15, 0x02}, { 400, 0x25, 0x02}, { 450, 0x06, 0x02}, + { 500, 0x16, 0x02}, { 550, 0x07, 0x03}, { 600, 0x17, 0x03}, + { 650, 0x08, 0x03}, { 700, 0x18, 0x03}, { 750, 0x09, 0x04}, + { 800, 0x19, 0x04}, { 850, 0x29, 0x04}, { 900, 0x39, 0x04}, + { 950, 0x0A, 0x05}, {1000, 0x1A, 0x05}, {1050, 0x2A, 0x05}, + {1100, 0x3A, 0x05}, {1150, 0x0B, 0x06}, {1200, 0x1B, 0x06}, + {1250, 0x2B, 0x06}, {1300, 0x3B, 0x06}, {1350, 0x0C, 0x07}, + {1400, 0x1C, 0x07}, {1450, 0x2C, 0x07}, {1500, 0x3C, 0x07} + }; + + if (phy == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (phy->status < INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (output_freq < MIN_OUTPUT_FREQ) + { + return ERR_DSI_PHY_FREQ_OUT_OF_BOUND; + } + + loop_divider = ((output_freq * (phy->reference_freq / DPHY_DIV_LOWER_LIMIT)) / phy->reference_freq); + /* here delta will account for the rounding */ + delta = ((loop_divider * phy->reference_freq) / (phy->reference_freq / DPHY_DIV_LOWER_LIMIT)) - output_freq; + for (input_divider = 1 + (phy->reference_freq / DPHY_DIV_UPPER_LIMIT); ((phy->reference_freq / input_divider) >= DPHY_DIV_LOWER_LIMIT) && (!flag); input_divider++) + { + tmp_loop_divider = ((output_freq * input_divider) / (phy->reference_freq)); + if ((tmp_loop_divider % 2) == 0) + { /* if even */ + if (output_freq == (tmp_loop_divider * (phy->reference_freq / input_divider))) + { /* exact values found */ + flag = 1; + loop_divider = tmp_loop_divider; + delta = output_freq - (tmp_loop_divider * (phy->reference_freq / input_divider)); + /* variable was incremented before exiting the loop */ + input_divider--; + } + if ((output_freq - (tmp_loop_divider * (phy->reference_freq / input_divider))) < delta) + { /* values found with smaller delta */ + loop_divider = tmp_loop_divider; + delta = output_freq - (tmp_loop_divider * (phy->reference_freq / input_divider)); + step = 1; + } + } + else + { + tmp_loop_divider += 1; + if (output_freq == (tmp_loop_divider * (phy->reference_freq / input_divider))) + { /* exact values found */ + flag = 1; + loop_divider = tmp_loop_divider; + delta = (tmp_loop_divider * (phy->reference_freq / input_divider)) - output_freq; + /* variable was incremented before exiting the loop */ + input_divider--; + } + if (((tmp_loop_divider * (phy->reference_freq / input_divider)) - output_freq) < delta) + { /* values found with smaller delta */ + loop_divider = tmp_loop_divider; + delta = (tmp_loop_divider * (phy->reference_freq / input_divider)) - output_freq; + step = 0; + } + } + } + if (!flag) + { + input_divider = step + (loop_divider * phy->reference_freq) / output_freq; +// phy->log_info("D-PHY: Approximated Frequency: %d KHz", (loop_divider * (phy->reference_freq / input_divider))); + } +#ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING + if (phy->phy_keep_work != true) +#endif + { + /* get the PHY in power down mode (shutdownz=0) and reset it (rstz=0) to + avoid transient periods in PHY operation during re-configuration procedures. */ + mipi_dsih_dphy_reset(phy, 0); + mipi_dsih_dphy_clock_en(phy, 0); + mipi_dsih_dphy_shutdown(phy, 0); + /* provide an initial active-high test clear pulse in TESTCLR */ + mipi_dsih_dphy_test_clear(phy, 1); + mipi_dsih_dphy_test_clear(phy, 0); + for(n=0;n<100;n++){ + ; + } + } + /* find ranges */ + for (range = 0; (range < (sizeof(ranges)/sizeof(ranges[0]))) && ((output_freq / 1000) > ranges[range].freq); range++) + { + ; + } + if (range >= (sizeof(ranges)/sizeof(ranges[0]))) + { + return ERR_DSI_PHY_FREQ_OUT_OF_BOUND; + } + /* set up board depending on environment if any */ + if (phy->bsp_pre_config != 0) + { + phy->bsp_pre_config(phy, 0); + } + + /* Jessica add - begin*/ + data[0] = 0x83;//0x44;//0x44;//0x40; //0x40: ok for 200 clock lane lpx /*about 52ns*/ + mipi_dsih_dphy_write(phy, 0x60, data, 1); +// data[0] = 0x0; //0xA6;//0xC6;//0xC6;//0x86; //0x48: ok for 200 prepare time +// mipi_dsih_dphy_write(phy, 0x61, data, 1); + +// data[0] = 0x0;//0x6a;//0x6a;//0x4a; //0x4a: ok for 200 zero time +// mipi_dsih_dphy_write(phy, 0x62, data, 1); + + data[0] = 0x83;//0x44;//0x40;//0x40; // 0x40: ok for 200 data lane lpx /*about 52ns*/ + mipi_dsih_dphy_write(phy, 0x70, data, 1); + +// data[0] = 0x0;// 0x84;//0x96;//0x96;//0x86; //0x48: ok for 200 prepare time +// mipi_dsih_dphy_write(phy, 0x71, data, 1); + +// data[0] = 0x0;//0x44;//0x44;//0x40; //0x4a: ok for 200 zero time +// mipi_dsih_dphy_write(phy, 0x72, data, 1); + + //data[0] = 0x44; + //mipi_dsih_dphy_write(phy, 0x73, data, 1); + + //data[0] = 0x7F; + //mipi_dsih_dphy_write(phy, 0x74, data, 1); + + /* Jessica add - end*/ + + data[0] = 0x70; + mipi_dsih_dphy_write(phy, 0x16, data, 1); + + /* setup digital part */ + /* hs frequency range [7]|[6:1]|[0]*/ + data[0] = (0 << 7) | (ranges[range].hs_freq << 1) | 0; + //data[0] = (0 << 7) | (0x23 << 1) | 0; + /*From ASIC, we need unmask this code to make the frequency correct*/ + mipi_dsih_dphy_write(phy, 0x44, data, 1); //Jessica remove for more accurate frequency + /* setup PLL */ + /* vco range [7]|[6:3]|[2:1]|[0] */ + data[0] = (1 << 7) | (ranges[range].vco_range << 3) | (0 << 1) | 0; + mipi_dsih_dphy_write(phy, 0x10, data, 1); //Jessica +#ifdef TESTCHIP + /* for all Gen2 testchips, bypass LP TX enable idle low power */ + data[0] = 0x80; + mipi_dsih_dphy_write(phy, 0x32, data, 1); + mipi_dsih_dphy_write(phy, 0x42, data, 1); + mipi_dsih_dphy_write(phy, 0x52, data, 1); + mipi_dsih_dphy_write(phy, 0x82, data, 1); + mipi_dsih_dphy_write(phy, 0x92, data, 1); +#endif + if ((loop_divider % 2) != 0) + { /* only odd integers are allowed (1 will be subtracted upon writing, + see below) */ + loop_divider -= 1; + + } + /* gen 2 associates the charge pump current and LPF resistor with the + output frequency ranges (and thus we simplify here to use the + counter/pointer of the following structure) */ + i = range; + data[0] = (0x00 << 6) | (0x01 << 5) | (0x01 << 4); + + mipi_dsih_dphy_write(phy, 0x19, data, 1); //Jessica + + /* PLL Lock bypass|charge pump current [7:4]|[3:0] */ + data[0] = (0x00 << 4) | (loop_bandwidth[i].cp_current << 0); + mipi_dsih_dphy_write(phy, 0x11, data, 1); //Jessica + /* bypass CP default|bypass LPF default| LPF resistor [7]|[6]|[5:0] */ + data[0] = (0x01 << 7) | (0x01 << 6) |(loop_bandwidth[i].lpf_resistor << 0); + mipi_dsih_dphy_write(phy, 0x12, data, 1); + /* PLL input divider ratio [7:0] */ + data[0] = input_divider - 1; + mipi_dsih_dphy_write(phy, 0x17, data, 1); //Jessica + + data[0] = 0x04; //short the delay time before BTA + mipi_dsih_dphy_write(phy, 0x07, data, 1); + +// data[0] = 1; +// mipi_dsih_dphy_write(phy, 0xB0, data, 1); + + data[0] = 0x8B; + mipi_dsih_dphy_write(phy, 0x22, data, 1); +// data[1] = mipi_dsih_dphy_test_data_out(phy); +// printk("sprdfb:mipi dphy config-->0x22 write:%x,read:%x \n",data[0],data[1]); + + no_of_bytes = 2; /* pll loop divider (code 0x18) takes only 2 bytes (10 bits in data) */ + for (i = 0; i < no_of_bytes; i++) + { + data[i] = ((uint8_t)((((loop_divider - 1) >> (5 * i)) & 0x1F) | (i << 7) )); + /* 7 is dependent on no_of_bytes + make sure 5 bits only of value are written at a time */ + } + /* PLL loop divider ratio - SET no|reserved|feedback divider [7]|[6:5]|[4:0] */ + mipi_dsih_dphy_write(phy, 0x18, data, no_of_bytes); + mipi_dsih_dphy_no_of_lanes(phy, no_of_lanes); +#ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING + if (phy->phy_keep_work != true) +#endif + { + mipi_dsih_dphy_stop_wait_time(phy, 0x1C); + mipi_dsih_dphy_clock_en(phy, 1); + for(n=0;n<100;n++){ + ; + } + mipi_dsih_dphy_shutdown(phy, 1); + for(n=0;n<100;n++){ + ; + } + mipi_dsih_dphy_reset(phy, 1); + } + return OK; +} +#else +dsih_error_t mipi_dsih_dphy_configure(dphy_t * phy, uint8_t no_of_lanes, uint32_t output_freq) +{ + uint32_t loop_divider = 0; /* (M) */ + uint32_t input_divider = 1; /* (N) */ + uint8_t data[4]; /* maximum data for now are 4 bytes per test mode*/ + uint8_t no_of_bytes = 0; + uint8_t i = 0; /* iterator */ + uint8_t n=0;/* iterator */ + uint8_t range = 0; /* ranges iterator */ + int flag = 0; +#ifdef DWC_MIPI_DPHY_BIDIR_TSMC40LP + struct + { + uint32_t freq; /* upper margin of frequency range */ + uint8_t hs_freq; /* hsfreqrange */ + uint8_t vco_range; /* vcorange */ + } + ranges[] = + { + {90, 0x00, 0x01}, {100, 0x10, 0x01}, {110, 0x20, 0x01}, + {125, 0x01, 0x01}, {140, 0x11, 0x01}, {150, 0x21, 0x01}, + {160, 0x02, 0x01}, {180, 0x12, 0x03}, {200, 0x22, 0x03}, + {210, 0x03, 0x03}, {240, 0x13, 0x03}, {250, 0x23, 0x03}, + {270, 0x04, 0x07}, {300, 0x14, 0x07}, {330, 0x24, 0x07}, + {360, 0x15, 0x07}, {400, 0x25, 0x07}, {450, 0x06, 0x07}, + {500, 0x16, 0x07}, {550, 0x07, 0x0f}, {600, 0x17, 0x0f}, + {650, 0x08, 0x0f}, {700, 0x18, 0x0f}, {750, 0x09, 0x0f}, + {800, 0x19, 0x0f}, {850, 0x0A, 0x0f}, {900, 0x1A, 0x0f}, + {950, 0x2A, 0x0f}, {1000, 0x3A, 0x0f} + }; + struct + { + uint32_t loop_div; /* upper limit of loop divider range */ + uint8_t cp_current; /* icpctrl */ + uint8_t lpf_resistor; /* lpfctrl */ + } + loop_bandwidth[] = + { + {32, 0x06, 0x10}, {64, 0x06, 0x10}, {128, 0x0C, 0x08}, + {256, 0x04, 0x04}, {512, 0x00, 0x01}, {768, 0x01, 0x01}, + {1000, 0x02, 0x01} + }; +#elif defined DPHY2Btql + struct + { + uint32_t loop_div; /* upper limit of loop divider range */ + uint8_t cp_current; /* icpctrl */ + uint8_t lpf_resistor; /* lpfctrl */ + } + loop_bandwidth[] = + { + {32, 0x0B, 0x00}, {64, 0x0A, 0x00}, {128, 0x09, 0x01}, + {256, 0x08, 0x03}, {512, 0x08, 0x07}, {768, 0x08, 0x0F}, + {1000, 0x08, 0x1F} + }; +#endif + if (phy == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (phy->status < INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + if (output_freq < MIN_OUTPUT_FREQ) + { + return ERR_DSI_PHY_FREQ_OUT_OF_BOUND; + } + /* find M and N dividers */ + for (input_divider = 1 + (phy->reference_freq / DPHY_DIV_UPPER_LIMIT); ((phy->reference_freq / input_divider) >= DPHY_DIV_LOWER_LIMIT) && (!flag); input_divider++) + { /* here the >= DPHY_DIV_LOWER_LIMIT is a phy constraint, formula should be above 1 MHz */ + if (((output_freq * input_divider) % (phy->reference_freq )) == 0) + { /* values found */ + loop_divider = ((output_freq * input_divider) / (phy->reference_freq )); + if (loop_divider >= 12) + { + flag = 1; + } + } + } + if ((!flag) || ((phy->reference_freq / input_divider) < DPHY_DIV_LOWER_LIMIT)) + { /* no exact value found in previous for loop */ + /* this solution is not favourable as jitter would be maximum */ + loop_divider = output_freq / DPHY_DIV_LOWER_LIMIT; + input_divider = phy->reference_freq / DPHY_DIV_LOWER_LIMIT; + } + else + { /* variable was incremented before exiting the loop */ + input_divider--; + } + for (i = 0; (i < (sizeof(loop_bandwidth)/sizeof(loop_bandwidth[0]))) && (loop_divider > loop_bandwidth[i].loop_div); i++) + { + ; + } + if (i >= (sizeof(loop_bandwidth)/sizeof(loop_bandwidth[0]))) + { + return ERR_DSI_PHY_FREQ_OUT_OF_BOUND; + } + printk("sprdfb: Gen1 D-PHY: Approximated Frequency: %d KHz\n", (loop_divider * (phy->reference_freq / input_divider))); +#ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING + if (phy->phy_keep_work != true) +#endif + { + /* get the PHY in power down mode (shutdownz=0) and reset it (rstz=0) to + avoid transient periods in PHY operation during re-configuration procedures. */ + mipi_dsih_dphy_reset(phy, 0); + mipi_dsih_dphy_clock_en(phy, 0); + mipi_dsih_dphy_shutdown(phy, 0); + /* provide an initial active-high test clear pulse in TESTCLR */ + mipi_dsih_dphy_test_clear(phy, 1); + mipi_dsih_dphy_test_clear(phy, 0); + } +#ifdef DWC_MIPI_DPHY_BIDIR_TSMC40LP + /* find ranges */ + for (range = 0; (range < (sizeof(ranges)/sizeof(ranges[0]))) && ((output_freq / 1000) > ranges[range].freq); range++) + { + ; + } + if (range >= (sizeof(ranges)/sizeof(ranges[0]))) + { + return ERR_DSI_PHY_FREQ_OUT_OF_BOUND; + } + /* set up board depending on environment if any */ + if (phy->bsp_pre_config != 0) + { + phy->bsp_pre_config(phy, 0); + } + + /* Jessica add - begin*/ + data[0] = 0x42;//0x44;//0x44;//0x40; //0x40: ok for 200 clock lane lpx /*about 52ns*/ + mipi_dsih_dphy_write(phy, 0x60, data, 1); + data[0] = 0x0; //0xA6;//0xC6;//0xC6;//0x86; //0x48: ok for 200 prepare time + mipi_dsih_dphy_write(phy, 0x61, data, 1); + + data[0] = 0x0;//0x6a;//0x6a;//0x4a; //0x4a: ok for 200 zero time + mipi_dsih_dphy_write(phy, 0x62, data, 1); + + data[0] = 0x42;//0x44;//0x40;//0x40; // 0x40: ok for 200 data lane lpx /*about 52ns*/ + mipi_dsih_dphy_write(phy, 0x70, data, 1); + + data[0] = 0x0;// 0x84;//0x96;//0x96;//0x86; //0x48: ok for 200 prepare time + mipi_dsih_dphy_write(phy, 0x71, data, 1); + + data[0] = 0x0;//0x44;//0x44;//0x40; //0x4a: ok for 200 zero time + mipi_dsih_dphy_write(phy, 0x72, data, 1); + + //data[0] = 0x44; + //mipi_dsih_dphy_write(phy, 0x73, data, 1); + + //data[0] = 0x7F; + //mipi_dsih_dphy_write(phy, 0x74, data, 1); + + /* Jessica add - end*/ + + /* setup digital part */ + /* hs frequency range [7]|[6:1]|[0]*/ + data[0] = (0 << 7) | (ranges[range].hs_freq << 1) | 0; + //data[0] = (0 << 7) | (0x23 << 1) | 0; + /*From ASIC, we need unmask this code to make the frequency correct*/ + mipi_dsih_dphy_write(phy, 0x44, data, 1); //Jessica remove for more accurate frequency + /* setup PLL */ + /* vco range [7]|[6:3]|[2:1]|[0] */ + data[0] = (1 << 7) | (ranges[range].vco_range << 3) | (0 << 1) | 0; + mipi_dsih_dphy_write(phy, 0x10, data, 1); //Jessica + /* PLL reserved|Input divider control|Loop Divider Control|Post Divider Ratio [7:6]|[5]|[4]|[3:0] */ + data[0] = (0x00 << 6) | (0x01 << 5) | (0x01 << 4) | (0x03 << 0); /* post divider default = 0x03 - it is only used for clock out 2*/ + mipi_dsih_dphy_write(phy, 0x19, data, 1); //Jessica +#elif defined DPHY2Btql + /* vco range [7:5]|[4]|[3]|[2:1]|[0] */ + data[0] = ((((output_freq / 1000) > 500 )? 1: 0) << 4) | (1 << 3) | (0 << 1) | 0; + mipi_dsih_dphy_write(phy, 0x10, data, 1); +#endif + /* PLL Lock bypass|charge pump current [7:4]|[3:0] */ + data[0] = (0x00 << 4) | (loop_bandwidth[i].cp_current << 0); + mipi_dsih_dphy_write(phy, 0x11, data, 1); //Jessica + /* bypass CP default|bypass LPF default| LPF resistor [7]|[6]|[5:0] */ + data[0] = (0x01 << 7) | (0x01 << 6) |(loop_bandwidth[i].lpf_resistor << 0); + mipi_dsih_dphy_write(phy, 0x12, data, 1); + /* PLL input divider ratio [7:0] */ + data[0] = input_divider - 1; + mipi_dsih_dphy_write(phy, 0x17, data, 1); //Jessica + + data[0] = 0x04; //short the delay time before BTA + mipi_dsih_dphy_write(phy, 0x07, data, 1); + +// data[0] = 1; +// mipi_dsih_dphy_write(phy, 0xB0, data, 1); + + data[0] = 0x8B; + mipi_dsih_dphy_write(phy, 0x22, data, 1); + // data[1] = mipi_dsih_dphy_test_data_out(phy); +// printk("sprdfb:mipi dphy config-->0x22 write:%x,read:%x \n",data[0],data[1]); + + no_of_bytes = 2; /* pll loop divider (code 0x18) takes only 2 bytes (10 bits in data) */ + for (i = 0; i < no_of_bytes; i++) + { + data[i] = ((uint8_t)((((loop_divider - 1) >> (5 * i)) & 0x1F) | (i << 7) )); + /* 7 is dependent on no_of_bytes + make sure 5 bits only of value are written at a time */ + } + /* PLL loop divider ratio - SET no|reserved|feedback divider [7]|[6:5]|[4:0] */ + mipi_dsih_dphy_write(phy, 0x18, data, no_of_bytes); + mipi_dsih_dphy_no_of_lanes(phy, no_of_lanes); +#ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING + if (phy->phy_keep_work != true) +#endif + { + mipi_dsih_dphy_stop_wait_time(phy, 0x1C); + mipi_dsih_dphy_clock_en(phy, 1); + for(n=0;n<100;n++){ + ; + } + mipi_dsih_dphy_shutdown(phy, 1); + for(n=0;n<100;n++){ + ; + } + mipi_dsih_dphy_reset(phy, 1); + } + return OK; +} +#endif +/** + * Close and power down D-PHY module + * @param phy pointer to structure which holds information about the d-phy + * module + * @return error code + */ +dsih_error_t mipi_dsih_dphy_close(dphy_t * phy) +{ + if (phy == 0) + { + return ERR_DSI_INVALID_INSTANCE; + } + else if ((phy->core_read_function == 0) || (phy->core_write_function == 0)) + { + return ERR_DSI_INVALID_IO; + } + if (phy->status < NOT_INITIALIZED) + { + return ERR_DSI_INVALID_INSTANCE; + } + mipi_dsih_dphy_reset(phy, 0); + mipi_dsih_dphy_reset(phy, 1); + mipi_dsih_dphy_shutdown(phy, 0); + phy->status = NOT_INITIALIZED; + return OK; +} +/** + * Enable clock lane module + * @param instance pointer to structure which holds information about the d-phy + * module + * @param en + */ +void mipi_dsih_dphy_clock_en(dphy_t * instance, int en) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_RSTZ, en, 2, 1); +} +/** + * Reset D-PHY module + * @param instance pointer to structure which holds information about the d-phy + * module + * @param reset + */ +void mipi_dsih_dphy_reset(dphy_t * instance, int reset) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_RSTZ, reset, 1, 1); +} +/** + * Power up/down D-PHY module + * @param instance pointer to structure which holds information about the d-phy + * module + * @param powerup (1) shutdown (0) + */ +void mipi_dsih_dphy_shutdown(dphy_t * instance, int powerup) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_RSTZ, powerup, 0, 1); +} +/** + * Force D-PHY PLL to stay on while in ULPS + * @param instance pointer to structure which holds information about the d-phy + * module + * @param force (1) disable (0) + * @note To follow the programming model, use wakeup_pll function + */ +void mipi_dsih_dphy_force_pll(dphy_t * instance, int force) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_RSTZ, force, 3, 1); +} +/** + * Get force D-PHY PLL module + * @param instance pointer to structure which holds information about the d-phy + * module + * @return force value + */ +int mipi_dsih_dphy_get_force_pll(dphy_t * instance) +{ + return mipi_dsih_dphy_read_part(instance, R_DPHY_RSTZ, 3, 1); +} +/** + * Wake up or make sure D-PHY PLL module is awake + * This function must be called after going into ULPS and before exiting it + * to force the DPHY PLLs to wake up. It will wait until the DPHY status is + * locked. It follows the procedure described in the user guide. + * This function should be used to make sure the PLL is awake, rather than + * the force_pll above. + * @param instance pointer to structure which holds information about the d-phy + * module + * @return error code + * @note this function has an active wait + */ +int mipi_dsih_dphy_wakeup_pll(dphy_t * instance) +{ + unsigned i = 0; + if (mipi_dsih_dphy_status(instance, 0x1) == 0) + { + mipi_dsih_dphy_force_pll(instance, 1); + for (i = 0; i < DSIH_PHY_ACTIVE_WAIT; i++) + { + if(mipi_dsih_dphy_status(instance, 0x1)) + { + break; + } + } + if (mipi_dsih_dphy_status(instance, 0x1) == 0) + { + return ERR_DSI_PHY_PLL_NOT_LOCKED; + } + } + return OK; +} +/** + * Configure minimum wait period for HS transmission request after a stop state + * @param instance pointer to structure which holds information about the d-phy + * module + * @param no_of_byte_cycles [in byte (lane) clock cycles] + */ +void mipi_dsih_dphy_stop_wait_time(dphy_t * instance, uint8_t no_of_byte_cycles) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_IF_CFG, no_of_byte_cycles, 8, 8); +} +/** + * Set number of active lanes + * @param instance pointer to structure which holds information about the d-phy + * module + * @param no_of_lanes + */ +void mipi_dsih_dphy_no_of_lanes(dphy_t * instance, uint8_t no_of_lanes) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_IF_CFG, no_of_lanes - 1, 0, 2); +} +/** + * Get number of currently active lanes + * @param instance pointer to structure which holds information about the d-phy + * module + * @return number of active lanes + */ +uint8_t mipi_dsih_dphy_get_no_of_lanes(dphy_t * instance) +{ + return mipi_dsih_dphy_read_part(instance, R_DPHY_IF_CFG, 0, 2); +} + +/** + * SPRD ADD + * Set non-continuous clock mode + * @param instance pointer to structure which holds information about the d-phy + * module + * @param enable + */ +void mipi_dsih_dphy_enable_nc_clk(dphy_t * instance, int enable) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_LPCLK_CTRL, enable, 1, 1); +} + +/** + * Request the PHY module to start transmission of high speed clock. + * This causes the clock lane to start transmitting DDR clock on the + * lane interconnect. + * @param instance pointer to structure which holds information about the d-phy + * module + * @param enable + * @note this function should be called explicitly by user always except for + * transmitting + */ +void mipi_dsih_dphy_enable_hs_clk(dphy_t * instance, int enable) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_LPCLK_CTRL, enable, 0, 1); +} +/** + * One bit is asserted in the trigger_request (4bits) to cause the lane module + * to cause the associated trigger to be sent across the lane interconnect. + * The trigger request is synchronous with the rising edge of the clock. + * @note: Only one bit of the trigger_request is asserted at any given time, the + * remaining must be left set to 0, and only when not in LPDT or ULPS modes + * @param instance pointer to structure which holds information about the d-phy + * module + * @param trigger_request 4 bit request + */ +dsih_error_t mipi_dsih_dphy_escape_mode_trigger(dphy_t * instance, uint8_t trigger_request) +{ + uint8_t sum = 0; + int i = 0; + for (i = 0; i < 4; i++) + { + sum += ((trigger_request >> i) & 1); + } + if (sum == 1) + { /* clear old trigger */ + mipi_dsih_dphy_write_part(instance, R_DPHY_TX_TRIGGERS, 0x00, 0, 4); + mipi_dsih_dphy_write_part(instance, R_DPHY_TX_TRIGGERS, trigger_request, 0, 4); + for (i = 0; i < DSIH_PHY_ACTIVE_WAIT; i++) + { + if(mipi_dsih_dphy_status(instance, 0x0010)) + { + break; + } + } + mipi_dsih_dphy_write_part(instance, R_DPHY_TX_TRIGGERS, 0x00, 0, 4); + if (i >= DSIH_PHY_ACTIVE_WAIT) + { + return ERR_DSI_TIMEOUT; + } + return OK; + } + return ERR_DSI_INVALID_COMMAND; +} +/** + * ULPS mode request/exit on all active data lanes. + * @param instance pointer to structure which holds information about the d-phy + * module + * @param enable (request 1/ exit 0) + * @return error code + * @note this is a blocking function. wait upon exiting the ULPS will exceed 1ms + */ +#ifdef GEN_2 +dsih_error_t mipi_dsih_dphy_ulps_data_lanes(dphy_t * instance, int enable) +{ + int timeout; + /* mask 1 0101 0010 0000 */ + uint16_t data_lanes_mask = 0; + if (enable) + { + mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 1, 2, 1); + return OK; + } + else + { + if (mipi_dsih_dphy_status(instance, 0x1) == 0) + { + return ERR_DSI_PHY_PLL_NOT_LOCKED; + } + mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 1, 3, 1); + switch (mipi_dsih_dphy_get_no_of_lanes(instance)) + { + case 3: + data_lanes_mask |= (1 << 12); + case 2: + data_lanes_mask |= (1 << 10); + case 1: + data_lanes_mask |= (1 << 8); + case 0: + data_lanes_mask |= (1 << 5); + break; + default: + data_lanes_mask = 0; + break; + } + for (timeout = 0; timeout < DSIH_PHY_ACTIVE_WAIT; timeout++) + { /* verify that the DPHY has left ULPM */ + + if (mipi_dsih_dphy_status(instance, data_lanes_mask) == data_lanes_mask) + { + break; + } + /* wait at least 1ms */ + for (timeout = 0; timeout < ONE_MS_ACTIVE_WAIT; timeout++) + { + ; + } + } + if (mipi_dsih_dphy_status(instance, data_lanes_mask) != data_lanes_mask) + { + instance->log_info("sprdfb: stat %x, mask %x", mipi_dsih_dphy_status(instance, data_lanes_mask), data_lanes_mask); + return ERR_DSI_TIMEOUT; + } + mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 0, 2, 1); + mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 0, 3, 1); + } + return OK; +} +#else +void mipi_dsih_dphy_ulps_data_lanes(dphy_t * instance, int enable) +{ + int timeout; + if (enable) + { + mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 3, 1); + } + else + { + mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 4, 1); + for (timeout = 0; timeout < DSIH_PHY_ACTIVE_WAIT; timeout++) + { /* verify that the DPHY has left ULPM */ + /* mask 1010100100000 */ + if (mipi_dsih_dphy_status(instance, 0x1520) == 0) + { /* wait at least 1ms */ + for (timeout = 0; timeout < ONE_MS_ACTIVE_WAIT; timeout++) + { + ; + } + break; + } + } + mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 3, 1); + mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 4, 1); + } +} +#endif +/** + * ULPS mode request/exit on Clock Lane. + * @param instance pointer to structure which holds information about the + * d-phy module + * @param enable 1 or disable 0 of the Ultra Low Power State of the clock lane + * @return error code + * @note this is a blocking function. wait upon exiting the ULPS will exceed 1ms + */ +#ifdef GEN_2 +dsih_error_t mipi_dsih_dphy_ulps_clk_lane(dphy_t * instance, int enable) +{ + int timeout; + /* mask 1000 */ + uint16_t clk_lane_mask = 0x0008; + if (enable) + { + /* mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 0, 0, 1); */ + mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 1, 0, 1); + } + else + { + if (mipi_dsih_dphy_status(instance, 0x1) == 0) + { + return ERR_DSI_PHY_PLL_NOT_LOCKED; + } + mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 1, 1, 1); + for (timeout = 0; timeout < DSIH_PHY_ACTIVE_WAIT; timeout++) + { /* verify that the DPHY has left ULPM */ + /* mask 1010100100000 */ + if (mipi_dsih_dphy_status(instance, clk_lane_mask) == clk_lane_mask) + { /* wait at least 1ms */ + instance->log_info("sprdfb: stat %x, mask %x", mipi_dsih_dphy_status(instance, clk_lane_mask), clk_lane_mask); + break; + } + /* wait at least 1ms */ + for (timeout = 0; timeout < ONE_MS_ACTIVE_WAIT; timeout++) + { /* dummy operation for the loop not to be optimised */ + enable = mipi_dsih_dphy_status(instance, clk_lane_mask); + } + } + if (mipi_dsih_dphy_status(instance, clk_lane_mask) != clk_lane_mask) + { + return ERR_DSI_TIMEOUT; + } + mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 0, 0, 1); + mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 0, 1, 1); + } + return OK; +} +#else +void mipi_dsih_dphy_ulps_clk_lane(dphy_t * instance, int enable) +{ + int timeout; + if (enable) + { + mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 0, 1); + mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 1, 1); + } + else + { + mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 2, 1); + for (timeout = 0; timeout < DSIH_PHY_ACTIVE_WAIT; timeout++) + { /* verify that the DPHY has left ULPM */ + /* mask 1010100100000 */ + if (mipi_dsih_dphy_status(instance, 0x0004) == 0) + { /* wait at least 1ms */ + for (timeout = 0; timeout < ONE_MS_ACTIVE_WAIT; timeout++) + { + ; + } + break; + } + } + mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 1, 1); + mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 2, 1); + } +} +#endif +/** + * Get D-PHY PPI status + * @param instance pointer to structure which holds information about the d-phy + * module + * @param mask + * @return status + */ +uint32_t mipi_dsih_dphy_status(dphy_t * instance, uint16_t mask) +{ + return mipi_dsih_dphy_read_word(instance, R_DPHY_STATUS) & mask; +} +/** + * @param instance pointer to structure which holds information about the d-phy + * module + * @param value + */ +void mipi_dsih_dphy_test_clock(dphy_t * instance, int value) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_TST_CRTL0, value, 1, 1); +} +/** + * @param instance pointer to structure which holds information about the d-phy + * module + * @param value + */ +void mipi_dsih_dphy_test_clear(dphy_t * instance, int value) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_TST_CRTL0, value, 0, 1); +} +/** + * @param instance pointer to structure which holds information about the d-phy + * module + * @param on_falling_edge + */ +void mipi_dsih_dphy_test_en(dphy_t * instance, uint8_t on_falling_edge) +{ + mipi_dsih_dphy_write_part(instance, R_DPHY_TST_CRTL1, on_falling_edge, 16, 1); +} +/** + * @param instance pointer to structure which holds information about the d-phy + * module + */ +uint8_t mipi_dsih_dphy_test_data_out(dphy_t * instance) +{ + return mipi_dsih_dphy_read_part(instance, R_DPHY_TST_CRTL1, 8, 8); +} +/** + * @param instance pointer to structure which holds information about the d-phy + * module + * @param test_data + */ +void mipi_dsih_dphy_test_data_in(dphy_t * instance, uint8_t test_data) +{ + mipi_dsih_dphy_write_word(instance, R_DPHY_TST_CRTL1, test_data); +} +/** + * Write to D-PHY module (encapsulating the digital interface) + * @param instance pointer to structure which holds information about the d-phy + * module + * @param address offset inside the D-PHY digital interface + * @param data array of bytes to be written to D-PHY + * @param data_length of the data array + */ +void mipi_dsih_dphy_write(dphy_t * instance, uint8_t address, uint8_t * data, uint8_t data_length) +{ + unsigned i = 0; + if (data != 0) + { +#if ((defined DWC_MIPI_DPHY_BIDIR_TSMC40LP) || (defined DPHY2Btql) || (defined GEN_2)) + /* set the TESTCLK input high in preparation to latch in the desired test mode */ + mipi_dsih_dphy_test_clock(instance, 1); + /* set the desired test code in the input 8-bit bus TESTDIN[7:0] */ + mipi_dsih_dphy_test_data_in(instance, address); + /* set TESTEN input high */ + mipi_dsih_dphy_test_en(instance, 1); + /* drive the TESTCLK input low; the falling edge captures the chosen test code into the transceiver */ + mipi_dsih_dphy_test_clock(instance, 0); + /* set TESTEN input low to disable further test mode code latching */ + mipi_dsih_dphy_test_en(instance, 0); + /* start writing MSB first */ + for (i = data_length; i > 0; i--) + { /* set TESTDIN[7:0] to the desired test data appropriate to the chosen test mode */ + mipi_dsih_dphy_test_data_in(instance, data[i - 1]); + /* pulse TESTCLK high to capture this test data into the macrocell; repeat these two steps as necessary */ + mipi_dsih_dphy_test_clock(instance, 1); + mipi_dsih_dphy_test_clock(instance, 0); + } +#endif + } +} + + + +/* abstracting BSP */ +/** + * Write to whole register to D-PHY module (encapsulating the bus interface) + * @param instance pointer to structure which holds information about the d-phy + * module + * @param reg_address offset + * @param data 32-bit word + */ +void mipi_dsih_dphy_write_word(dphy_t * instance, uint32_t reg_address, uint32_t data) +{ + if (instance->core_write_function != 0) + { + instance->core_write_function(instance->address, reg_address, data); + } +} +/** + * Write bit field to D-PHY module (encapsulating the bus interface) + * @param instance pointer to structure which holds information about the d-phy + * module + * @param reg_address offset + * @param data bits to be written to D-PHY + * @param shift from the right hand side of the register (big endian) + * @param width of the bit field + */ +void mipi_dsih_dphy_write_part(dphy_t * instance, uint32_t reg_address, uint32_t data, uint8_t shift, uint8_t width) +{ + uint32_t mask = 0; + uint32_t temp = 0; + if (instance->core_read_function != 0) + { + mask = (1 << width) - 1; + temp = mipi_dsih_dphy_read_word(instance, reg_address); + temp &= ~(mask << shift); + temp |= (data & mask) << shift; + mipi_dsih_dphy_write_word(instance, reg_address, temp); + } +} +/** + * Read whole register from D-PHY module (encapsulating the bus interface) + * @param instance pointer to structure which holds information about the d-phy + * module + * @param reg_address offset + * @return data 32-bit word + */ +uint32_t mipi_dsih_dphy_read_word(dphy_t * instance, uint32_t reg_address) +{ + if (instance->core_read_function == 0) + { + return ERR_DSI_INVALID_IO; + } + return instance->core_read_function(instance->address, reg_address); +} +/** + * Read bit field from D-PHY module (encapsulating the bus interface) + * @param instance pointer to structure which holds information about the d-phy + * module + * @param reg_address offset + * @param shift from the right hand side of the register (big endian) + * @param width of the bit field + * @return data bits to be written to D-PHY + */ +uint32_t mipi_dsih_dphy_read_part(dphy_t * instance, uint32_t reg_address, uint8_t shift, uint8_t width) +{ + return (mipi_dsih_dphy_read_word(instance, reg_address) >> shift) & ((1 << width) - 1); +} diff --git a/drivers/autotst/mipi_dsih_dphy.h b/drivers/autotst/mipi_dsih_dphy.h new file mode 100644 index 00000000..c171fe28 --- /dev/null +++ b/drivers/autotst/mipi_dsih_dphy.h @@ -0,0 +1,67 @@ +/* + * @file mipi_dsih_dphy.h + * + * Synopsys Inc. + * SG DWC PT02 + */ + +#ifndef MIPI_DSIH_DPHY_H_ +#define MIPI_DSIH_DPHY_H_ + +#include "mipi_dsih_local.h" + +#define R_DPHY_LPCLK_CTRL (0x94) +#define R_DPHY_RSTZ (0xA0) +#define R_DPHY_IF_CFG (0xA4) +#define R_DPHY_ULPS_CTRL (0xA8) +#define R_DPHY_TX_TRIGGERS (0xAC) +#define R_DPHY_STATUS (0xB0) +#define R_DPHY_TST_CRTL0 (0xB4) +#define R_DPHY_TST_CRTL1 (0xB8) + +#ifdef FB_DSIH_VERSION_1P21A +#define R_DSI_HOST_PHY_IF_CTRL 0x5CUL +#endif + + + +/* obligatory functions - code can be changed for different phys*/ +dsih_error_t mipi_dsih_dphy_open(dphy_t * phy); +dsih_error_t mipi_dsih_dphy_configure(dphy_t * phy, uint8_t no_of_lanes, uint32_t output_freq); +dsih_error_t mipi_dsih_dphy_close(dphy_t * phy); + +void mipi_dsih_dphy_clock_en(dphy_t * instance, int en); +void mipi_dsih_dphy_reset(dphy_t * instance, int reset); +void mipi_dsih_dphy_shutdown(dphy_t * instance, int powerup); +int mipi_dsih_dphy_get_force_pll(dphy_t * instance); +void mipi_dsih_dphy_force_pll(dphy_t * instance, int force); +int mipi_dsih_dphy_wakeup_pll(dphy_t * instance); + +void mipi_dsih_dphy_stop_wait_time(dphy_t * instance, uint8_t no_of_byte_cycles); +void mipi_dsih_dphy_no_of_lanes(dphy_t * instance, uint8_t no_of_lanes); +uint8_t mipi_dsih_dphy_get_no_of_lanes(dphy_t * instance); +void mipi_dsih_dphy_enable_nc_clk(dphy_t * instance, int enable); +void mipi_dsih_dphy_enable_hs_clk(dphy_t * instance, int enable); +dsih_error_t mipi_dsih_dphy_escape_mode_trigger(dphy_t * instance, uint8_t trigger_request); +#ifdef GEN_2 +dsih_error_t mipi_dsih_dphy_ulps_data_lanes(dphy_t * instance, int enable); +dsih_error_t mipi_dsih_dphy_ulps_clk_lane(dphy_t * instance, int enable); +#else +void mipi_dsih_dphy_ulps_data_lanes(dphy_t * instance, int enable); +void mipi_dsih_dphy_ulps_clk_lane(dphy_t * instance, int enable); +#endif +uint32_t mipi_dsih_dphy_status(dphy_t * instance, uint16_t mask); +/* end of obligatory functions*/ +void mipi_dsih_dphy_test_clock(dphy_t * instance, int value); +void mipi_dsih_dphy_test_clear(dphy_t * instance, int value); +void mipi_dsih_dphy_test_en(dphy_t * instance, uint8_t on_falling_edge); +uint8_t mipi_dsih_dphy_test_data_out(dphy_t * instance); +void mipi_dsih_dphy_test_data_in(dphy_t * instance, uint8_t test_data); + +void mipi_dsih_dphy_write(dphy_t * instance, uint8_t address, uint8_t * data, uint8_t data_length); + +void mipi_dsih_dphy_write_word(dphy_t * instance, uint32_t reg_address, uint32_t data); +void mipi_dsih_dphy_write_part(dphy_t * instance, uint32_t reg_address, uint32_t data, uint8_t shift, uint8_t width); +uint32_t mipi_dsih_dphy_read_word(dphy_t * instance, uint32_t reg_address); +uint32_t mipi_dsih_dphy_read_part(dphy_t * instance, uint32_t reg_address, uint8_t shift, uint8_t width); +#endif /* MIPI_DSIH_DPHY_H_ */ diff --git a/drivers/autotst/mipi_dsih_hal.c b/drivers/autotst/mipi_dsih_hal.c new file mode 100644 index 00000000..d20693f5 --- /dev/null +++ b/drivers/autotst/mipi_dsih_hal.c @@ -0,0 +1,1114 @@ +/** + * @file mipi_dsih_hal.c + * @brief Hardware Abstraction Level of DWC MIPI DSI HOST controller + * + * Synopsys Inc. + * SG DWC PT02 + */ +#include "mipi_dsih_hal.h" + +/** + * Write a 32-bit word to the DSI Host core + * @param instance pointer to structure holding the DSI Host core information + * @param reg_address register offset in core + * @param data 32-bit word to be written to register + */ +void mipi_dsih_write_word(dsih_ctrl_t * instance, uint32_t reg_address, uint32_t data) +{ + + instance->core_write_function(instance->address, reg_address, data); +} +/** + * Write a bit field o a 32-bit word to the DSI Host core + * @param instance pointer to structure holding the DSI Host core information + * @param reg_address register offset in core + * @param data to be written to register + * @param shift bit shift from the left (system is BIG ENDIAN) + * @param width of bit field + */ +void mipi_dsih_write_part(dsih_ctrl_t * instance, uint32_t reg_address, uint32_t data, uint8_t shift, uint8_t width) +{ + uint32_t mask = (1 << width) - 1; + uint32_t temp = mipi_dsih_read_word(instance, reg_address); + + temp &= ~(mask << shift); + temp |= (data & mask) << shift; + mipi_dsih_write_word(instance, reg_address, temp); +} +/** + * Write a 32-bit word to the DSI Host core + * @param instance pointer to structure holding the DSI Host core information + * @param reg_address offset of register + * @return 32-bit word value stored in register + */ +uint32_t mipi_dsih_read_word(dsih_ctrl_t * instance, uint32_t reg_address) +{ + return instance->core_read_function(instance->address, reg_address); +} +/** + * Write a 32-bit word to the DSI Host core + * @param instance pointer to structure holding the DSI Host core information + * @param reg_address offset of register in core + * @param shift bit shift from the left (system is BIG ENDIAN) + * @param width of bit field + * @return bit field read from register + */ +uint32_t mipi_dsih_read_part(dsih_ctrl_t * instance, uint32_t reg_address, uint8_t shift, uint8_t width) +{ + return (mipi_dsih_read_word(instance, reg_address) >> shift) & ((1 << width) - 1); +} +/** + * Get DSI Host core version + * @param instance pointer to structure holding the DSI Host core information + * @return ascii number of the version + */ +uint32_t mipi_dsih_hal_get_version(dsih_ctrl_t * instance) +{ + return mipi_dsih_read_word(instance, R_DSI_HOST_VERSION); +} +/** + * Modify power status of DSI Host core + * @param instance pointer to structure holding the DSI Host core information + * @param on (1) or off (0) + */ +void mipi_dsih_hal_power(dsih_ctrl_t * instance, int on) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_PWR_UP, on, 0, 1); +} +/** + * Get the power status of the DSI Host core + * @param instance pointer to structure holding the DSI Host core information + * @return power status + */ +int mipi_dsih_hal_get_power(dsih_ctrl_t * instance) +{ + return (int)(mipi_dsih_read_part(instance, R_DSI_HOST_PWR_UP, 0, 1)); +} +/** + * Write transmission escape timeout + * a safe guard so that the state machine would reset if transmission + * takes too long + * @param instance pointer to structure holding the DSI Host core information + * @param tx_escape_division + */ +void mipi_dsih_hal_tx_escape_division(dsih_ctrl_t * instance, uint8_t tx_escape_division) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_CLK_MGR, tx_escape_division, 0, 8); +} +/** + * Write the DPI video virtual channel destination + * @param instance pointer to structure holding the DSI Host core information + * @param vc virtual channel + */ +void mipi_dsih_hal_dpi_video_vc(dsih_ctrl_t * instance, uint8_t vc) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_DPI_VCID, (uint32_t)(vc), 0, 2); +} +/** + * Get the DPI video virtual channel destination + * @param instance pointer to structure holding the DSI Host core information + * @return virtual channel + */ +uint8_t mipi_dsih_hal_dpi_get_video_vc(dsih_ctrl_t * instance) +{ + return mipi_dsih_read_part(instance, R_DSI_HOST_DPI_VCID, 0, 2); +} +/** + * Set DPI video color coding + * @param instance pointer to structure holding the DSI Host core information + * @param color_coding enum (configuration and color depth) + * @return error code + */ +dsih_error_t mipi_dsih_hal_dpi_color_coding(dsih_ctrl_t * instance, dsih_color_coding_t color_coding) +{ + dsih_error_t err = OK; + if (color_coding > COLOR_CODE_MAX) + { + if (instance->log_error != 0) + { + instance->log_error("sprdfb: invalid colour configuration"); + } + err = ERR_DSI_COLOR_CODING; + } + else + { + mipi_dsih_write_part(instance, R_DSI_HOST_DPI_COLOR_CODE, color_coding, 0, 4); + } + return err; +} +/** + * Get DPI video color coding + * @param instance pointer to structure holding the DSI Host core information + * @return color coding enum (configuration and color depth) + */ +dsih_color_coding_t mipi_dsih_hal_dpi_get_color_coding(dsih_ctrl_t * instance) +{ + return (dsih_color_coding_t)(mipi_dsih_read_part(instance, R_DSI_HOST_DPI_COLOR_CODE, 0, 4)); +} +/** + * Get DPI video color depth + * @param instance pointer to structure holding the DSI Host core information + * @return number of bits per pixel + */ +uint8_t mipi_dsih_hal_dpi_get_color_depth(dsih_ctrl_t * instance) +{ + uint8_t color_depth = 0; + switch (mipi_dsih_read_part(instance, R_DSI_HOST_DPI_COLOR_CODE, 0, 4)) + { + case 0: + case 1: + case 2: + color_depth = 16; + break; + case 3: + case 4: + color_depth = 18; + break; + case 5: + color_depth = 24; + break; + case 6: + color_depth = 20; + break; + case 7: + color_depth = 24; + break; + case 8: + color_depth = 16; + break; + case 9: + color_depth = 30; + break; + case 10: + color_depth = 36; + break; + case 11: + color_depth = 12; + break; + default: + break; + } + return color_depth; +} +/** + * Get DPI video pixel configuration + * @param instance pointer to structure holding the DSI Host core information + * @return pixel configuration + */ +uint8_t mipi_dsih_hal_dpi_get_color_config(dsih_ctrl_t * instance) +{ + uint8_t color_config = 0; + switch (mipi_dsih_read_part(instance, R_DSI_HOST_DPI_COLOR_CODE, 0, 4)) + { + case 0: + color_config = 1; + break; + case 1: + color_config = 2; + break; + case 2: + color_config = 3; + break; + case 3: + color_config = 1; + break; + case 4: + color_config = 2; + break; + default: + color_config = 0; + break; + } + return color_config; +} +/** + * Set DPI loosely packetisation video (used only when color depth = 18 + * @param instance pointer to structure holding the DSI Host core information + * @param enable + */ +void mipi_dsih_hal_dpi_18_loosely_packet_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_DPI_COLOR_CODE, enable, 8, 1); +} +/** + * Set DPI color mode pin polarity + * @param instance pointer to structure holding the DSI Host core information + * @param active_low (1) or active high (0) + */ +void mipi_dsih_hal_dpi_color_mode_pol(dsih_ctrl_t * instance, int active_low) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_DPI_CFG_POL, active_low, 4, 1); +} +/** + * Set DPI shut down pin polarity + * @param instance pointer to structure holding the DSI Host core information + * @param active_low (1) or active high (0) + */ +void mipi_dsih_hal_dpi_shut_down_pol(dsih_ctrl_t * instance, int active_low) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_DPI_CFG_POL, active_low, 3, 1); +} +/** + * Set DPI horizontal sync pin polarity + * @param instance pointer to structure holding the DSI Host core information + * @param active_low (1) or active high (0) + */ +void mipi_dsih_hal_dpi_hsync_pol(dsih_ctrl_t * instance, int active_low) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_DPI_CFG_POL, active_low, 2, 1); +} +/** + * Set DPI vertical sync pin polarity + * @param instance pointer to structure holding the DSI Host core information + * @param active_low (1) or active high (0) + */ +void mipi_dsih_hal_dpi_vsync_pol(dsih_ctrl_t * instance, int active_low) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_DPI_CFG_POL, active_low, 1, 1); +} +/** + * Set DPI data enable pin polarity + * @param instance pointer to structure holding the DSI Host core information + * @param active_low (1) or active high (0) + */ +void mipi_dsih_hal_dpi_dataen_pol(dsih_ctrl_t * instance, int active_low) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_DPI_CFG_POL, active_low, 0, 1); +} +/** + * Enable FRAME BTA ACK + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_dpi_frame_ack_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_MODE_CFG, enable, 14, 1); +} +/** + * Enable null packets (value in null packet size will be taken in calculations) + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + * @note function retained for backward compatibility (not used from 1.20a on) + */ +void mipi_dsih_hal_dpi_null_packet_en(dsih_ctrl_t * instance, int enable) +{ +} +/** + * Enable multi packets (value in no of chunks will be taken in calculations) + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_dpi_multi_packet_en(dsih_ctrl_t * instance, int enable) +{ +} +/** + * Enable return to low power mode inside horizontal front porch periods when + * timing allows + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_dpi_lp_during_hfp(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_MODE_CFG, enable, 13, 1); +} +/** + * Enable return to low power mode inside horizontal back porch periods when + * timing allows + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_dpi_lp_during_hbp(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_MODE_CFG, enable, 12, 1); +} +/** + * Enable return to low power mode inside vertical active lines periods when + * timing allows + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_dpi_lp_during_vactive(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_MODE_CFG, enable, 11, 1); +} +/** + * Enable return to low power mode inside vertical front porch periods when + * timing allows + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_dpi_lp_during_vfp(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_MODE_CFG, enable, 10, 1); +} +/** + * Enable return to low power mode inside vertical back porch periods when + * timing allows + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_dpi_lp_during_vbp(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_MODE_CFG, enable, 9, 1); +} +/** + * Enable return to low power mode inside vertical sync periods when + * timing allows + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_dpi_lp_during_vsync(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_MODE_CFG, enable, 8, 1); +} +/** + * Set DPI video mode type (burst/non-burst - with sync pulses or events) + * @param instance pointer to structure holding the DSI Host core information + * @param type + * @return error code + */ +dsih_error_t mipi_dsih_hal_dpi_video_mode_type(dsih_ctrl_t * instance, dsih_video_mode_t type) +{ + if (type < 3) + { + mipi_dsih_write_part(instance, R_DSI_HOST_VID_MODE_CFG, type, 0, 2); + return OK; + } + else + { + if (instance->log_error != 0) + { + instance->log_error("sprdfb: undefined type"); + } + return ERR_DSI_OUT_OF_BOUND; + } +} +/** + * Enable/disable DPI video mode + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_dpi_video_mode_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_MODE_CFG, enable? 0: 1, 0, 1); +} +/** + * Get the status of video mode, whether enabled or not in core + * @param instance pointer to structure holding the DSI Host core information + * @return status + */ +int mipi_dsih_hal_dpi_is_video_mode(dsih_ctrl_t * instance) +{ + return (mipi_dsih_read_part(instance, R_DSI_HOST_MODE_CFG, 0, 1) == 0); +} +/** + * Write the null packet size - will only be taken into account when null + * packets are enabled. + * @param instance pointer to structure holding the DSI Host core information + * @param size of null packet + * @return error code + */ +dsih_error_t mipi_dsih_hal_dpi_null_packet_size(dsih_ctrl_t * instance, uint16_t size) +{ + if (size < (1 << 13)) /* 13-bit field */ + { + mipi_dsih_write_part(instance, R_DSI_HOST_VID_NULL_SIZE, size, 0, 13); + return OK; + } + else + { + return ERR_DSI_OUT_OF_BOUND; + } +} +/** + * Write no of chunks to core - taken into consideration only when multi packet + * is enabled + * @param instance pointer to structure holding the DSI Host core information + * @param no of chunks + */ +dsih_error_t mipi_dsih_hal_dpi_chunks_no(dsih_ctrl_t * instance, uint16_t no) +{ + if (no < (1 << 13)) + { + mipi_dsih_write_part(instance, R_DSI_HOST_VID_NUM_CHUNKS, no, 0, 13); + return OK; + } + else + { + return ERR_DSI_OUT_OF_BOUND; + } +} +/** + * Write video packet size. obligatory for sending video + * @param instance pointer to structure holding the DSI Host core information + * @param size of video packet - containing information + * @return error code + */ +dsih_error_t mipi_dsih_hal_dpi_video_packet_size(dsih_ctrl_t * instance, uint16_t size) +{ + if (size < (1 << 14)) /* 14-bit field */ + { + mipi_dsih_write_part(instance, R_DSI_HOST_VID_PKT_SIZE, size, 0, 14); + return OK; + } + else + { + return ERR_DSI_OUT_OF_BOUND; + } +} +/** + * function retained for backward compatibility (not used from 1.20a on) + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_edpi_enable(dsih_ctrl_t * instance, int enable) +{ +} +/** + * Specifiy the size of the packet memory write start/continue + * @param instance pointer to structure holding the DSI Host core information + * @ size of the packet + * @note when different than zero (0) eDPI is enabled + */ +void mipi_dsih_hal_edpi_max_allowed_size(dsih_ctrl_t * instance, uint16_t size) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_EDPI_CMD_SIZE, size, 0, 16); +} +/** + * Enable tear effect acknowledge + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_tear_effect_ack_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, enable, 0, 1); +} +/** + * Enable packets acknowledge request after each packet transmission + * @param instance pointer to structure holding the DSI Host core information + * @param enable (1) - disable (0) + */ +void mipi_dsih_hal_cmd_ack_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, enable, 1, 1); +} +/** + * Set DCS command packet transmission to transmission type + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_param of command + * @param lp transmit in low power + * @return error code + */ +dsih_error_t mipi_dsih_hal_dcs_wr_tx_type(dsih_ctrl_t * instance, unsigned no_of_param, int lp) +{ + switch (no_of_param) + { + case 0: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 16, 1); + break; + case 1: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 17, 1); + break; + default: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 19, 1); + break; + } + return OK; +} +/** + * Set DCS read command packet transmission to transmission type + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_param of command + * @param lp transmit in low power + * @return error code + */ +dsih_error_t mipi_dsih_hal_dcs_rd_tx_type(dsih_ctrl_t * instance, unsigned no_of_param, int lp) +{ + dsih_error_t err = OK; + switch (no_of_param) + { + case 0: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 18, 1); + break; + default: + if (instance->log_error != 0) + { + instance->log_error("sprdfb: undefined DCS Read packet type"); + } + err = ERR_DSI_OUT_OF_BOUND; + break; + } + return err; +} + +/*Jessica add begin: to support max read packet size command */ +dsih_error_t mipi_dsih_hal_max_rd_packet_size_type(dsih_ctrl_t * instance, int lp) +{ + dsih_error_t err = OK; + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 10, 1); + return err; +} +/*Jessica add end*/ + +/** + * Set generic write command packet transmission to transmission type + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_param of command + * @param lp transmit in low power + * @return error code + */ +dsih_error_t mipi_dsih_hal_gen_wr_tx_type(dsih_ctrl_t * instance, unsigned no_of_param, int lp) +{ + switch (no_of_param) + { + case 0: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 8, 1); + break; + case 1: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 9, 1); + break; + case 2: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 10, 1); + break; + default: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 14, 1); + break; + } + return OK; +} +/** + * Set generic command packet transmission to transmission type + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_param of command + * @param lp transmit in low power + * @return error code + */ +dsih_error_t mipi_dsih_hal_gen_rd_tx_type(dsih_ctrl_t * instance, unsigned no_of_param, int lp) +{ + dsih_error_t err = OK; + switch (no_of_param) + { + case 0: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 11, 1); + break; + case 1: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 12, 1); + break; + case 2: + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 13, 1); + break; + default: + if (instance->log_error != 0) + { + instance->log_error("sprdfb: undefined Generic Read packet type"); + } + err = ERR_DSI_OUT_OF_BOUND; + break; + } + return err; +} +/** + * Configure maximum read packet size command transmission type + * @param instance pointer to structure holding the DSI Host core information + * @param lp set to low power + */ +void mipi_dsih_hal_max_rd_size_tx_type(dsih_ctrl_t * instance, int lp) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_CMD_MODE_CFG, lp, 24, 1); +} +/** + * Enable command mode (Generic interface) + * @param instance pointer to structure holding the DSI Host core information + * @param enable + */ +void mipi_dsih_hal_gen_cmd_mode_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_MODE_CFG, enable? 1: 0, 0, 1); +} +/** + * Retrieve the controller's status of whether command mode is ON or not + * @param instance pointer to structure holding the DSI Host core information + * @return whether command mode is ON + */ +int mipi_dsih_hal_gen_is_cmd_mode(dsih_ctrl_t * instance) +{ + return (mipi_dsih_read_part(instance, R_DSI_HOST_MODE_CFG, 0, 1) == 1); +} +/** + * Configure the Horizontal Line time + * @param instance pointer to structure holding the DSI Host core information + * @param time taken to transmit the total of the horizontal line + */ +void mipi_dsih_hal_dpi_hline(dsih_ctrl_t * instance, uint16_t time) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_HLINE_TIME, time, 0, 15); +} +/** + * Configure the Horizontal back porch time + * @param instance pointer to structure holding the DSI Host core information + * @param time taken to transmit the horizontal back porch + */ +void mipi_dsih_hal_dpi_hbp(dsih_ctrl_t * instance, uint16_t time) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_HBP_TIME, time, 0, 12); +} +/** + * Configure the Horizontal sync time + * @param instance pointer to structure holding the DSI Host core information + * @param time taken to transmit the horizontal sync + */ +void mipi_dsih_hal_dpi_hsa(dsih_ctrl_t * instance, uint16_t time) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_HSA_TIME, time, 0, 12); +} +/** + * Configure the vertical active lines of the video stream + * @param instance pointer to structure holding the DSI Host core information + * @param lines + */ +void mipi_dsih_hal_dpi_vactive(dsih_ctrl_t * instance, uint16_t lines) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_VACTIVE_LINES, lines, 0, 14); +} +/** + * Configure the vertical front porch lines of the video stream + * @param instance pointer to structure holding the DSI Host core information + * @param lines + */ +void mipi_dsih_hal_dpi_vfp(dsih_ctrl_t * instance, uint16_t lines) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_VFP_LINES, lines, 0, 10); +} +/** + * Configure the vertical back porch lines of the video stream + * @param instance pointer to structure holding the DSI Host core information + * @param lines + */ +void mipi_dsih_hal_dpi_vbp(dsih_ctrl_t * instance, uint16_t lines) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_VBP_LINES, lines, 0, 10); +} +/** + * Configure the vertical sync lines of the video stream + * @param instance pointer to structure holding the DSI Host core information + * @param lines + */ +void mipi_dsih_hal_dpi_vsync(dsih_ctrl_t * instance, uint16_t lines) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_VID_VSA_LINES, lines, 0, 10); +} +/** + * configure timeout divisions (so they would have more clock ticks) + * @param instance pointer to structure holding the DSI Host core information + * @param byte_clk_division_factor no of hs cycles before transiting back to LP in + * (lane_clk / byte_clk_division_factor) + */ +void mipi_dsih_hal_timeout_clock_division(dsih_ctrl_t * instance, uint8_t byte_clk_division_factor) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_CLK_MGR, byte_clk_division_factor, 8, 8); +} +/** + * Configure the Low power receive time out + * @param instance pointer to structure holding the DSI Host core information + * @param count (of byte cycles) + */ +void mipi_dsih_hal_lp_rx_timeout(dsih_ctrl_t * instance, uint16_t count) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_TO_CNT_CFG, count, 0, 16); +} +/** + * Configure a high speed transmission time out7 + * @param instance pointer to structure holding the DSI Host core information + * @param count (byte cycles) + */ +void mipi_dsih_hal_hs_tx_timeout(dsih_ctrl_t * instance, uint16_t count) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_TO_CNT_CFG, count, 16, 16); +} +/** + * Get the error 0 interrupt register status + * @param instance pointer to structure holding the DSI Host core information + * @param mask the mask to be read from the register + * @return error status 0 value + */ +uint32_t mipi_dsih_hal_int_status_0(dsih_ctrl_t * instance, uint32_t mask) +{ + return (mipi_dsih_read_word(instance, R_DSI_HOST_INT_ST0) & mask); +} +/** + * Get the error 1 interrupt register status + * @param instance pointer to structure holding the DSI Host core information + * @param mask the mask to be read from the register + * @return error status 1 value + */ +uint32_t mipi_dsih_hal_int_status_1(dsih_ctrl_t * instance, uint32_t mask) +{ + return (mipi_dsih_read_word(instance, R_DSI_HOST_INT_ST1) & mask); +} +/** + * Configure MASK (hiding) of interrupts coming from error 0 source + * @param instance pointer to structure holding the DSI Host core information + * @param mask to be written to the register + */ +void mipi_dsih_hal_int_mask_0(dsih_ctrl_t * instance, uint32_t mask) +{ + mipi_dsih_write_word(instance, R_DSI_HOST_INT_MSK0, mask); +} +/** + * Get the ERROR MASK 0 register status + * @param instance pointer to structure holding the DSI Host core information + * @param mask the bits to read from the mask register + */ +uint32_t mipi_dsih_hal_int_get_mask_0(dsih_ctrl_t * instance, uint32_t mask) +{ + return (mipi_dsih_read_word(instance, R_DSI_HOST_INT_MSK0) & mask); +} +/** + * Configure MASK (hiding) of interrupts coming from error 0 source + * @param instance pointer to structure holding the DSI Host core information + * @param mask the mask to be written to the register + */ +void mipi_dsih_hal_int_mask_1(dsih_ctrl_t * instance, uint32_t mask) +{ + mipi_dsih_write_word(instance, R_DSI_HOST_INT_MSK1, mask); +} +/** + * Get the ERROR MASK 1 register status + * @param instance pointer to structure holding the DSI Host core information + * @param mask the bits to read from the mask register + */ +uint32_t mipi_dsih_hal_int_get_mask_1(dsih_ctrl_t * instance, uint32_t mask) +{ + return (mipi_dsih_read_word(instance, R_DSI_HOST_INT_MSK1) & mask); +} +/* DBI NOT IMPLEMENTED */ +void mipi_dsih_hal_dbi_out_color_coding(dsih_ctrl_t * instance, uint8_t color_depth, uint8_t option); +void mipi_dsih_hal_dbi_in_color_coding(dsih_ctrl_t * instance, uint8_t color_depth, uint8_t option); +void mipi_dsih_hal_dbi_lut_size(dsih_ctrl_t * instance, uint8_t size); +void mipi_dsih_hal_dbi_partitioning_en(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dbi_dcs_vc(dsih_ctrl_t * instance, uint8_t vc); +void mipi_dsih_hal_dbi_max_cmd_size(dsih_ctrl_t * instance, uint16_t size); +void mipi_dsih_hal_dbi_cmd_size(dsih_ctrl_t * instance, uint16_t size); +void mipi_dsih_hal_dbi_max_cmd_size(dsih_ctrl_t * instance, uint16_t size); +int mipi_dsih_hal_dbi_rd_cmd_busy(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_read_fifo_full(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_read_fifo_empty(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_write_fifo_full(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_write_fifo_empty(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_cmd_fifo_full(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_cmd_fifo_empty(dsih_ctrl_t * instance); + +/** + * Write command header in the generic interface + * (which also sends DCS commands) as a subset + * @param instance pointer to structure holding the DSI Host core information + * @param vc of destination + * @param packet_type (or type of DCS command) + * @param ls_byte (if DCS, it is the DCS command) + * @param ms_byte (only parameter of short DCS packet) + * @return error code + */ +dsih_error_t mipi_dsih_hal_gen_packet_header(dsih_ctrl_t * instance, uint8_t vc, uint8_t packet_type, uint8_t ms_byte, uint8_t ls_byte) +{ + if (vc < 4) + { + mipi_dsih_write_part(instance, R_DSI_HOST_GEN_HDR, (ms_byte << 16) | (ls_byte << 8 ) | ((vc << 6) | packet_type), 0, 24); + return OK; + } + return ERR_DSI_OVERFLOW; +} +/** + * Write the payload of the long packet commands + * @param instance pointer to structure holding the DSI Host core information + * @param payload array of bytes of payload + * @return error code + */ +dsih_error_t mipi_dsih_hal_gen_packet_payload(dsih_ctrl_t * instance, uint32_t payload) +{ + if (mipi_dsih_hal_gen_write_fifo_full(instance)) + { + return ERR_DSI_OVERFLOW; + } + mipi_dsih_write_word(instance, R_DSI_HOST_GEN_PLD_DATA, payload); + return OK; + +} +/** + * Write the payload of the long packet commands + * @param instance pointer to structure holding the DSI Host core information + * @param payload pointer to 32-bit array to hold read information + * @return error code + */ +dsih_error_t mipi_dsih_hal_gen_read_payload(dsih_ctrl_t * instance, uint32_t* payload) +{ + *payload = mipi_dsih_read_word(instance, R_DSI_HOST_GEN_PLD_DATA); + return OK; +} + +/** + * Configure the read back virtual channel for the generic interface + * @param instance pointer to structure holding the DSI Host core information + * @param vc to listen to on the line + */ +void mipi_dsih_hal_gen_rd_vc(dsih_ctrl_t * instance, uint8_t vc) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_GEN_VCID, vc, 0, 2); +} +/** + * Enable EOTp reception + * @param instance pointer to structure holding the DSI Host core information + * @param enable + */ +void mipi_dsih_hal_gen_eotp_rx_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_PCKHDL_CFG, enable, 1, 1); +} +/** + * Enable EOTp transmission + * @param instance pointer to structure holding the DSI Host core information + * @param enable + */ +void mipi_dsih_hal_gen_eotp_tx_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_PCKHDL_CFG, enable, 0, 1); +} +/** + * Enable Bus Turn-around request + * @param instance pointer to structure holding the DSI Host core information + * @param enable + */ +void mipi_dsih_hal_bta_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_PCKHDL_CFG, enable, 2, 1); +} +/** + * Enable ECC reception, error correction and reporting + * @param instance pointer to structure holding the DSI Host core information + * @param enable + */ +void mipi_dsih_hal_gen_ecc_rx_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_PCKHDL_CFG, enable, 3, 1); +} +/** + * Enable CRC reception, error reporting + * @param instance pointer to structure holding the DSI Host core information + * @param enable + */ +void mipi_dsih_hal_gen_crc_rx_en(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_PCKHDL_CFG, enable, 4, 1); +} +/** + * Get status of read command + * @param instance pointer to structure holding the DSI Host core information + * @return 1 if busy + */ +int mipi_dsih_hal_gen_rd_cmd_busy(dsih_ctrl_t * instance) +{ + return mipi_dsih_read_part(instance, R_DSI_HOST_CMD_PKT_STATUS, 6, 1); +} +/** + * Get the FULL status of generic read payload fifo + * @param instance pointer to structure holding the DSI Host core information + * @return 1 if fifo full + */ +int mipi_dsih_hal_gen_read_fifo_full(dsih_ctrl_t * instance) +{ + return mipi_dsih_read_part(instance, R_DSI_HOST_CMD_PKT_STATUS, 5, 1); +} +/** + * Get the EMPTY status of generic read payload fifo + * @param instance pointer to structure holding the DSI Host core information + * @return 1 if fifo empty + */ +int mipi_dsih_hal_gen_read_fifo_empty(dsih_ctrl_t * instance) +{ + return mipi_dsih_read_part(instance, R_DSI_HOST_CMD_PKT_STATUS, 4, 1); +} +/** + * Get the FULL status of generic write payload fifo + * @param instance pointer to structure holding the DSI Host core information + * @return 1 if fifo full + */ +int mipi_dsih_hal_gen_write_fifo_full(dsih_ctrl_t * instance) +{ + return mipi_dsih_read_part(instance, R_DSI_HOST_CMD_PKT_STATUS, 3, 1); +} +/** + * Get the EMPTY status of generic write payload fifo + * @param instance pointer to structure holding the DSI Host core information + * @return 1 if fifo empty + */ +int mipi_dsih_hal_gen_write_fifo_empty(dsih_ctrl_t * instance) +{ + return mipi_dsih_read_part(instance, R_DSI_HOST_CMD_PKT_STATUS, 2, 1); +} +/** + * Get the FULL status of generic command fifo + * @param instance pointer to structure holding the DSI Host core information + * @return 1 if fifo full + */ +int mipi_dsih_hal_gen_cmd_fifo_full(dsih_ctrl_t * instance) +{ + return mipi_dsih_read_part(instance, R_DSI_HOST_CMD_PKT_STATUS, 1, 1); +} +/** + * Get the EMPTY status of generic command fifo + * @param instance pointer to structure holding the DSI Host core information + * @return 1 if fifo empty + */ +int mipi_dsih_hal_gen_cmd_fifo_empty(dsih_ctrl_t * instance) +{ + return mipi_dsih_read_part(instance, R_DSI_HOST_CMD_PKT_STATUS, 0, 1); +} +/* only if DPI */ +/** + * Configure how many cycles of byte clock would the PHY module take + * to switch data lane from high speed to low power + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles + * @return error code + */ +dsih_error_t mipi_dsih_phy_hs2lp_config(dsih_ctrl_t * instance, uint8_t no_of_byte_cycles) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_PHY_TMR_CFG, no_of_byte_cycles, 24, 8); + return OK; +} +/** + * Configure how many cycles of byte clock would the PHY module take + * to switch the data lane from to low power high speed + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles + * @return error code + */ +dsih_error_t mipi_dsih_phy_lp2hs_config(dsih_ctrl_t * instance, uint8_t no_of_byte_cycles) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_PHY_TMR_CFG, no_of_byte_cycles, 16, 8); + return OK; +} +/** + * Configure how many cycles of byte clock would the PHY module take + * to switch clock lane from high speed to low power + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles + * @return error code + */ +dsih_error_t mipi_dsih_phy_clk_hs2lp_config(dsih_ctrl_t * instance, uint8_t no_of_byte_cycles) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_PHY_TMR_LPCLK_CFG, no_of_byte_cycles, 16, 10); + return OK; +} +/** + * Configure how many cycles of byte clock would the PHY module take + * to switch clock lane from to low power high speed + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles + * @return error code + */ +dsih_error_t mipi_dsih_phy_clk_lp2hs_config(dsih_ctrl_t * instance, uint8_t no_of_byte_cycles) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_PHY_TMR_LPCLK_CFG, no_of_byte_cycles, 0, 10); + return OK; +} +/** + * Configure how many cycles of byte clock would the PHY module take + * to turn the bus around to start receiving + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles + * @return error code + */ +dsih_error_t mipi_dsih_phy_bta_time(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + /*Jessica modified: From ASIC, the second table in spec is correct, this 15 bits are max rd time*/ + if (no_of_byte_cycles < 0x8000) /* 15-bit field */ + { + //mipi_dsih_write_part(instance, R_DSI_HOST_PHY_TMR_CFG, no_of_byte_cycles, 0, 12); + mipi_dsih_write_part(instance, R_DSI_HOST_PHY_TMR_CFG, no_of_byte_cycles, 0, 15); + } + else + { + return ERR_DSI_OVERFLOW; + } + return OK; +} +/** + * Enable the automatic mechanism to stop providing clock in the clock + * lane when time allows + * @param instance pointer to structure holding the DSI Host core information + * @param enable + * @return error code + */ +void mipi_dsih_non_continuous_clock(dsih_ctrl_t * instance, int enable) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_LPCLK_CTRL, enable, 1, 1); +} +/** + * Get the status of the automatic mechanism to stop providing clock in the + * clock lane when time allows + * @param instance pointer to structure holding the DSI Host core information + * @return status 1 (enabled) 0 (disabled) + */ +int mipi_dsih_non_continuous_clock_status(dsih_ctrl_t * instance) +{ + return mipi_dsih_read_part(instance, R_DSI_HOST_LPCLK_CTRL, 1, 1); +} +/* PRESP Time outs */ +/** + * Timeout for peripheral (for controller to stay still) after LP data + * transmission write requests + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the + * link still, after sending a low power write operation. This period is + * measured in cycles of lanebyteclk + */ +void mipi_dsih_hal_presp_timeout_low_power_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_LP_WR_TO_CNT, no_of_byte_cycles, 0, 16); +} +/** + * Timeout for peripheral (for controller to stay still) after LP data + * transmission read requests + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the + * link still, after sending a low power read operation. This period is + * measured in cycles of lanebyteclk + */ +void mipi_dsih_hal_presp_timeout_low_power_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_LP_RD_TO_CNT, no_of_byte_cycles, 0, 16); +} +/** + * Timeout for peripheral (for controller to stay still) after HS data + * transmission write requests + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the + * link still, after sending a high-speed write operation. This period is + * measured in cycles of lanebyteclk + */ +void mipi_dsih_hal_presp_timeout_high_speed_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_HS_WR_TO_CNT, no_of_byte_cycles, 0, 16); +} +/** + * Timeout for peripheral between HS data transmission read requests + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the + * link still, after sending a high-speed read operation. This period is + * measured in cycles of lanebyteclk + */ +void mipi_dsih_hal_presp_timeout_high_speed_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_HS_RD_TO_CNT, no_of_byte_cycles, 0, 16); +} +/** + * Timeout for peripheral (for controller to stay still) after bus turn around + * @param instance pointer to structure holding the DSI Host core information + * @param no_of_byte_cycles period for which the DWC_mipi_dsi_host keeps the + * link still, after sending a BTA operation. This period is + * measured in cycles of lanebyteclk + */ +void mipi_dsih_hal_presp_timeout_bta(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles) +{ + mipi_dsih_write_part(instance, R_DSI_HOST_BTA_TO_CNT, no_of_byte_cycles, 0, 16); +} diff --git a/drivers/autotst/mipi_dsih_hal.h b/drivers/autotst/mipi_dsih_hal.h new file mode 100644 index 00000000..72c6ff75 --- /dev/null +++ b/drivers/autotst/mipi_dsih_hal.h @@ -0,0 +1,1804 @@ +/* + * @file mipi_dsih_hal.h + * + * Synopsys Inc. + * SG DWC PT02 + */ +/* + The Synopsys Software Driver and documentation (hereinafter "Software") + is an unsupported proprietary work of Synopsys, Inc. unless otherwise + expressly agreed to in writing between Synopsys and you. + + The Software IS NOT an item of Licensed Software or Licensed Product under + any End User Software License Agreement or Agreement for Licensed Product + with Synopsys or any supplement thereto. Permission is hereby granted, + free of charge, to any person obtaining a copy of this software annotated + with this license and the Software, to deal in the Software without + restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject + to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + */ + +#ifndef MIPI_DSIH_HAL_H_ +#define MIPI_DSIH_HAL_H_ + +#include "mipi_dsih_local.h" + +#define R_DSI_HOST_VERSION (0x00) +#define R_DSI_HOST_PWR_UP (0x04) +#define R_DSI_HOST_CLK_MGR (0x08) +#define R_DSI_HOST_DPI_VCID (0x0C) +#define R_DSI_HOST_DPI_COLOR_CODE (0x10) +#define R_DSI_HOST_DPI_CFG_POL (0x14) +#define R_DSI_HOST_DPI_LP_CMD_TIM (0x18) +#define R_DSI_HOST_DBI_VCID (0x1C) +#define R_DSI_HOST_DBI_CFG (0x20) +#define R_DSI_HOST_DBI_PARTITION_EN (0x24) +#define R_DSI_HOST_DBI_CMDSIZE (0x28) +#define R_DSI_HOST_PCKHDL_CFG (0x2C) +#define R_DSI_HOST_GEN_VCID (0x30) +#define R_DSI_HOST_MODE_CFG (0x34) +#define R_DSI_HOST_VID_MODE_CFG (0x38) +#define R_DSI_HOST_VID_PKT_SIZE (0x3C) +#define R_DSI_HOST_VID_NUM_CHUNKS (0x40) +#define R_DSI_HOST_VID_NULL_SIZE (0x44) +#define R_DSI_HOST_VID_HSA_TIME (0x48) +#define R_DSI_HOST_VID_HBP_TIME (0x4C) +#define R_DSI_HOST_VID_HLINE_TIME (0x50) +#define R_DSI_HOST_VID_VSA_LINES (0x54) +#define R_DSI_HOST_VID_VBP_LINES (0x58) +#define R_DSI_HOST_VID_VFP_LINES (0x5C) +#define R_DSI_HOST_VID_VACTIVE_LINES (0x60) +#define R_DSI_HOST_EDPI_CMD_SIZE (0x64) +#define R_DSI_HOST_CMD_MODE_CFG (0x68) +#define R_DSI_HOST_GEN_HDR (0x6C) +#define R_DSI_HOST_GEN_PLD_DATA (0x70) +#define R_DSI_HOST_CMD_PKT_STATUS (0x74) +#define R_DSI_HOST_TO_CNT_CFG (0x78) +#define R_DSI_HOST_HS_RD_TO_CNT (0x7C) +#define R_DSI_HOST_LP_RD_TO_CNT (0x80) +#define R_DSI_HOST_HS_WR_TO_CNT (0x84) +#define R_DSI_HOST_LP_WR_TO_CNT (0x88) +#define R_DSI_HOST_BTA_TO_CNT (0x8C) + +#define R_DSI_HOST_SDF_3D (0x90) + +#define R_DSI_HOST_LPCLK_CTRL (0x94) +#define R_DSI_HOST_PHY_TMR_LPCLK_CFG (0x98) +#define R_DSI_HOST_PHY_TMR_CFG (0x9C) +#define R_DSI_HOST_INT_ST0 (0xBC) +#define R_DSI_HOST_INT_ST1 (0xC0) +#define R_DSI_HOST_INT_MSK0 (0xC4) +#define R_DSI_HOST_INT_MSK1 (0xC8) +#define R_DSI_HOST_PHY_STATUS (0xB0) + + + +typedef enum _Dsi_Int0_Type_ { + ack_with_err_0, + ack_with_err_1, + ack_with_err_2, + ack_with_err_3, + ack_with_err_4, + ack_with_err_5, + ack_with_err_6, + ack_with_err_7, + ack_with_err_8, + ack_with_err_9, + ack_with_err_10, + ack_with_err_11, + ack_with_err_12, + ack_with_err_13, + ack_with_err_14, + ack_with_err_15, + dphy_errors_0, + dphy_errors_1, + dphy_errors_2, + dphy_errors_3, + dphy_errors_4, + DSI_INT0_MAX, +}Dsi_Int0_Type; + +typedef enum _Dsi_Int1_Type_ { + to_hs_tx, + to_lp_rx, + ecc_single_err, + ecc_multi_err, + crc_err, + pkt_size_err, + eopt_err, + dpi_pld_wr_err, + gen_cmd_wr_err, + gen_pld_wr_err, + gen_pld_send_err, + gen_pld_rd_err, + gen_pld_recv_err, + dbi_cmd_wr_err, + dbi_pld_wr_err, + dbi_pld_rd_err, + dbi_pld_recv_err, + dbi_illegal_comm_err, + DSI_INT1_MAX, +}Dsi_Int1_Type; +#define DSI_INT_MASK0_SET(bit,val)\ +{\ + uint32_t reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK0);\ + reg_val = (val == 1)?(reg_val | (1UL< 0. Otherwise, multiple chunks are used to transmit each video line. + */ +volatile unsigned int reserved_0 : + 19; //[31:13] Reserved + } + mBits; + volatile unsigned int dValue; + }VID_NUM_CHUNKS;// 0x0040 + + union _DSIH1P21A_VID_NULL_SIZE_tag_t { + struct _DSIH1P21A_VID_NULL_SIZE_map_t + { +volatile unsigned int vid_null_size : + 13; //[12:0] + /* + This register configures the number of bytes inside a null packet. + Setting it to 0 disables the null packets. + */ +volatile unsigned int reserved_0 : + 19; //[31:13] Reserved + } + mBits; + volatile unsigned int dValue; + }VID_NULL_SIZE;// 0x0044 + + union _DSIH1P21A_VID_HSA_TIME_tag_t { + struct _DSIH1P21A_VID_HSA_TIME_map_t + { +volatile unsigned int vid_hsa_time : + 12; //[11:0] This field configures the Horizontal Synchronism Active period in lane byte clock cycles +volatile unsigned int reserved_0 : + 20; //[31:12] Reserved + } + mBits; + volatile unsigned int dValue; + }VID_HSA_TIME;// 0x0048 + + union _DSIH1P21A_VID_HBP_TIME_tag_t { + struct _DSIH1P21A_VID_HBP_TIME_map_t + { +volatile unsigned int vid_hbp_time : + 12; //[11:0] This field configures the Horizontal Back Porch period in lane byte clock cycles. +volatile unsigned int reserved_0 : + 20; //[31:12] Reserved + } + mBits; + volatile unsigned int dValue; + }VID_HBP_TIME;// 0x004C + + union _DSIH1P21A_VID_HLINE_TIME_tag_t { + struct _DSIH1P21A_VID_HLINE_TIME_map_t + { +volatile unsigned int vid_hline_time : + 15; //[14:0] This field configures the size of the total line time (HSA+HBP+HACT+HFP) counted in lane byte clock cycles. +volatile unsigned int reserved_0 : + 17; //[31:15] Reserved + } + mBits; + volatile unsigned int dValue; + }VID_HLINE_TIME;// 0x0050 + + union _DSIH1P21A_VID_VSA_LINES_tag_t { + struct _DSIH1P21A_VID_VSA_LINES_map_t + { +volatile unsigned int vsa_lines : + 10; //[9:0] This field configures the Vertical Synchronism Active period measured in number of horizontal lines +volatile unsigned int reserved_0 : + 22; //[31:10] Reserved + } + mBits; + volatile unsigned int dValue; + }VID_VSA_LINES;// 0x0054 + + union _DSIH1P21A_VID_VBP_LINES_tag_t { + struct _DSIH1P21A_VID_VBP_LINES_map_t + { +volatile unsigned int vbp_lines : + 10; //[9:0] This field configures the Vertical Back Porch period measured in number of horizontal lines. +volatile unsigned int reserved_0 : + 22; //[31:10] Reserved + } + mBits; + volatile unsigned int dValue; + }VID_VBP_LINES;// 0x0058 + + union _DSIH1P21A_VID_VFP_LINES_tag_t { + struct _DSIH1P21A_VID_VFP_LINES_map_t + { +volatile unsigned int vfp_lines : + 10; //[9:0] This field configures the Vertical Front Porch period measured in number of horizontal lines. +volatile unsigned int reserved_0 : + 22; //[31:10] Reserved + } + mBits; + volatile unsigned int dValue; + }VID_VFP_LINES;// 0x005C + + union _DSIH1P21A_VID_VACTIVE_LINES_tag_t { + struct _DSIH1P21A_VID_VACTIVE_LINES_map_t + { +volatile unsigned int v_active_lines : + 14; //[13:0] This field configures the Vertical Active period measured in number of horizontal lines. +volatile unsigned int reserved_0 : + 18; //[31:14] Reserved + } + mBits; + volatile unsigned int dValue; + }VID_VACTIVE_LINES;// 0x0060 + + union _DSIH1P21A_EDPI_CMD_SIZE_tag_t { + struct _DSIH1P21A_EDPI_CMD_SIZE_map_t + { +volatile unsigned int edpi_allowed_cmd_size : + 16; //[15:0] This field configures the maximum allowed size for an eDPI write memory command, measured in pixels. Automatic partitioning of data obtained from eDPI is permanently enabled. +volatile unsigned int reserved_0 : + 16; //[31:16] Reserved + } + mBits; + volatile unsigned int dValue; + }EDPI_CMD_SIZE;// 0x0064 + + union _DSIH1P21A_CMD_MODE_CFG_tag_t { + struct _DSIH1P21A_CMD_MODE_CFG_map_t + { +volatile unsigned int tear_fx_en : + 1; //[0] When set to 1, this bit enables the tearing effect acknowledge request. +volatile unsigned int ack_rqst_en : + 1; //[1] When set to 1, this bit enables the acknowledge request after each packet transmission. +volatile unsigned int reserved_0 : + 6; //[7:2] +volatile unsigned int gen_sw_0p_tx : + 1; //[8] This bit configures the Generic short write packet with zero parameter command transmission type:0: High-speed 1: Low-power +volatile unsigned int gen_sw_1p_tx : + 1; //[9] This bit configures the Generic short write packet with one parameter command transmission type: 0: High-speed 1: Low-power +volatile unsigned int gen_sw_2p_tx : + 1; //[10] This bit configures the Generic short write packet with two parameters command transmission type:0: High-speed 1: Low-power +volatile unsigned int gen_sr_0p_tx : + 1; //[11] This bit configures the Generic short read packet with zero parameter command transmission type:0: High-speed 1: Low-power +volatile unsigned int gen_sr_1p_tx : + 1; //[12] This bit configures the Generic short read packet with one parameter command transmission type:0: High-speed 1: Low-power +volatile unsigned int gen_sr_2p_tx : + 1; //[13] This bit configures the Generic short read packet with two parameters command transmission type:0: High-speed 1: Low-power +volatile unsigned int gen_lw_tx : + 1; //[14] This bit configures the Generic long write packet command transmission type:0: High-speed 1: Low-power +volatile unsigned int reserved_1 : + 1; //[15] +volatile unsigned int dcs_sw_0p_tx : + 1; //[16] This bit configures the DCS short write packet with zero parameter command transmission type:0: High-speed 1: Low-power +volatile unsigned int dcs_sw_1p_tx : + 1; //[17] This bit configures the DCS short write packet with one parameter command transmission type:0: High-speed 1: Low-power +volatile unsigned int dcs_sr_0p_tx : + 1; //[18] This bit configures the DCS short read packet with zero parameter command transmission type:0: High-speed 1: Low-power +volatile unsigned int dcs_lw_tx : + 1; //[19] This bit configures the DCS long write packet command transmission type:0: High-speed 1: Low-power +volatile unsigned int reserved_2 : + 4; //[23:20] +volatile unsigned int max_rd_pkt_size : + 1; //[24] This bit configures the maximum read packet size command transmission type:0: High-speed 1: Low-power +volatile unsigned int reserved_3 : + 7; //[31:25] + } + mBits; + volatile unsigned int dValue; + }CMD_MODE_CFG;// 0x0068 + + union _DSIH1P21A_GEN_HDR_tag_t { + struct _DSIH1P21A_GEN_HDR_map_t + { +volatile unsigned int gen_dt : + 6; //[5:0] This field configures the packet data type of the header packet. +volatile unsigned int gen_vc : + 2; //[7:6] Reserved +volatile unsigned int gen_wc_lsbyte : + 8; //[15:8] This field configures the least significant byte of the header packet's Word count for long packets or data 0 for short packets. +volatile unsigned int gen_wc_msbyte : + 8; //[23:16] This field configures the most significant byte of the header packet's word count for long packets or data 1 for short packets. +volatile unsigned int reserved_0 : + 8; //[31:24] Reserved + } + mBits; + volatile unsigned int dValue; + }GEN_HDR;// 0x006C + + union _DSIH1P21A_GEN_PLD_DATA_tag_t { + struct _DSIH1P21A_GEN_PLD_DATA_map_t + { +volatile unsigned int gen_pld_b1 : + 8; //[7:0] This field indicates byte 1 of the packet payload. +volatile unsigned int gen_pld_b2 : + 8; //[15:8] This field indicates byte 2 of the packet payload. +volatile unsigned int gen_pld_b3 : + 8; //[23:16] This field indicates byte 3 of the packet payload. +volatile unsigned int gen_pld_b4 : + 8; //[31:24] This field indicates byte 4 of the packet payload. + } + mBits; + volatile unsigned int dValue; + }GEN_PLD_DATA;// 0x0070 + + union _DSIH1P21A_CMD_PKT_STATUS_tag_t { + struct _DSIH1P21A_CMD_PKT_STATUS_map_t + { +volatile unsigned int gen_cmd_empty : + 1; //[0] + /* + This bit indicates the empty status of the generic command FIFO. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved. + Value after reset: 0x1 + */ +volatile unsigned int gen_cmd_full : + 1; //[1] + /* + This bit indicates the full status of the generic command FIFO. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved. + Value after reset: 0x0 + */ +volatile unsigned int gen_pld_w_empty : + 1; //[2] + /* + This bit indicates the empty status of the generic write payload FIFO. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved. + Value after reset: 0x1 + */ +volatile unsigned int gen_pld_w_full : + 1; //[3] + /* + This bit indicates the full status of the generic write payload FIFO. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved. + Value after reset: 0x0 + */ +volatile unsigned int gen_pld_r_empty : + 1; //[4] + /* + This bit indicates the empty status of the generic read payload FIFO. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved. + Value after reset: 0x1 + */ +volatile unsigned int gen_pld_r_full : + 1; //[5] + /* + This bit indicates the full status of the generic read payload FIFO. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved. + Value after reset: 0x0 + */ +volatile unsigned int gen_rd_cmd_busy : + 1; //[6] + /* + This bit is set when a read command is issued and cleared when the + entire response is stored in the FIFO. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved. + Value after reset: 0x0 + */ +volatile unsigned int reserved_0 : + 1; //[7] + /* + */ +volatile unsigned int dbi_cmd_empy : + 1; //[8] + /* + This bit indicates the empty status of the DBI command FIFO. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + Value after reset: 0x1 + */ +volatile unsigned int dbi_cmd_full : + 1; //[9] + /* + This bit indicates the full status of the DBI command FIFO. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + Value after reset: 0x0 + */ +volatile unsigned int dbi_pld_w_empty : + 1; //[10] + /* + This bit indicates the empty status of the DBI write payload FIFO. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + Value after reset: 0x1 + */ +volatile unsigned int dbi_pld_w_full : + 1; //[11] + /* + This bit indicates the full status of the DBI write payload FIFO. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + Value after reset: 0x0 + */ +volatile unsigned int dbi_pld_r_empty : + 1; //[12] + /* + This bit indicates the empty status of the DBI read payload FIFO. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + Value after reset: 0x1 + */ +volatile unsigned int dbi_pld_r_full : + 1; //[13] + /* + This bit indicates the full status of the DBI read payload FIFO. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + Value after reset: 0x0 + */ +volatile unsigned int dbi_rd_cmd_busy : + 1; //[14] + /* + This bit is set when a read command is issued and cleared when the + entire response is stored in the FIFO. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + Value after reset: 0x0 + */ +volatile unsigned int reserved_1 : + 17; //[31:15] + } + mBits; + volatile unsigned int dValue; + } + CMD_PKT_STATUS;// 0x0074 + + union _DSIH1P21A_TO_CNT_CFG_tag_t { + struct _DSIH1P21A_TO_CNT_CFG_map_t + { +volatile unsigned int lprx_to_cnt : + 16; //[15:0] + /* + This field configures the timeout counter that triggers a low-power + reception timeout contention detection (measured in + TO_CLK_DIVISION cycles). + */ +volatile unsigned int hstx_to_cnt : + 16; //[31:16] + /* + This field configures the timeout counter that triggers a high-speed + transmission timeout contention detection (measured in + TO_CLK_DIVISION cycles). + If using the non-burst mode and there is no sufficient time to switch + from HS to LP and back in the period which is from one line data + finishing to the next line sync start, the DSI link returns the LP state + once per frame, then you should configure the TO_CLK_DIVISION + and hstx_to_cnt to be in accordance with: + hstx_to_cnt * lanebyteclkperiod * TO_CLK_DIVISION >= the time of + one FRAME data transmission * (1 + 10%) + In burst mode, RGB pixel packets are time-compressed, leaving more + time during a scan line. Therefore, if in burst mode and there is + sufficient time to switch from HS to LP and back in the period of time + from one line data finishing to the next line sync start, the DSI link can + return LP mode and back in this time interval to save power. For this, + configure the TO_CLK_DIVISION and hstx_to_cnt to be in accordance + with: + hstx_to_cnt * lanebyteclkperiod * TO_CLK_DIVISION >= the time of + one LINE data transmission * (1 + 10%) + */ + } + mBits; + volatile unsigned int dValue; + } + TO_CNT_CFG;// 0x0078 + + union _DSIH1P21A_HS_RD_TO_CNT_tag_t { + struct _DSIH1P21A_HS_RD_TO_CNT_map_t + { +volatile unsigned int hs_rd_to_cnt : + 16; //[15:0] + /* + This field sets a period for which the DWC_mipi_dsi_host keeps the + link still, after sending a high-speed read operation. This period is + measured in cycles of lanebyteclk. The counting starts when the + D-PHY enters the Stop state and causes no interrupts. + */ +volatile unsigned int reserved_0 : + 16; //[31:16] + } + mBits; + volatile unsigned int dValue; + } + HS_RD_TO_CNT;// 0x007C + + union _DSIH1P21A_LP_RD_TO_CNT_tag_t { + struct _DSIH1P21A_LP_RD_TO_CNT_map_t + { +volatile unsigned int lp_rd_to_cnt : + 16; //[15:0] + /* + This field sets a period for which the DWC_mipi_dsi_host keeps the + link still, after sending a low-power read operation. This period is + measured in cycles of lanebyteclk. The counting starts when the + D-PHY enters the Stop state and causes no interrupts. + */ +volatile unsigned int reserved_0 : + 16; //[31:16] + } + mBits; + volatile unsigned int dValue; + } + LP_RD_TO_CNT;// 0x0080 + + union _DSIH1P21A_HS_WR_TO_CNT_tag_t { + struct _DSIH1P21A_HS_WR_TO_CNT_map_t + { +volatile unsigned int hs_wr_to_cnt : + 16; //[15:0] + /* + This field sets a period for which the DWC_mipi_dsi_host keeps the + link inactive after sending a high-speed write operation. This period is + measured in cycles of lanebyteclk. The counting starts when the + D-PHY enters the Stop state and causes no interrupts. + */ +volatile unsigned int reserved_0 : + 8; //[23:16] +volatile unsigned int presp_to_mode : + 1; //[24] + /* + When set to 1, this bit ensures that the peripheral response timeout + caused by hs_wr_to_cnt is used only once per eDPI frame, when both + the following conditions are met: + dpivsync_edpiwms has risen and fallen. + Packets originated from eDPI have been transmitted and its FIFO + is empty again. + In this scenario no non-eDPI requests are sent to the D-PHY, even if + there is traffic from generic or DBI ready to be sent, making it return to + stop state. When it does so, PRESP_TO counter is activated and only + when it finishes does the controller send any other traffic that is ready. + Dependency: DSI_DATAINTERFACE = 4. Otherwise, this bit is + reserved. + */ +volatile unsigned int reserved_1 : + 7; //[31:25] + } + mBits; + volatile unsigned int dValue; + } + HS_WR_TO_CNT;// 0x0084 + + union _DSIH1P21A_LP_WR_TO_CNT_tag_t { + struct _DSIH1P21A_LP_WR_TO_CNT_map_t + { +volatile unsigned int lp_wr_to_cnt : + 16; //[15:0] + /* + This field sets a period for which the DWC_mipi_dsi_host keeps the + link still, after sending a low-power write operation. This period is + measured in cycles of lanebyteclk. The counting starts when the + D-PHY enters the Stop state and causes no interrupts + */ +volatile unsigned int reserved_0 : + 16; //[31:16] + } + mBits; + volatile unsigned int dValue; + } + LP_WR_TO_CNT;// 0x0088 + + union _DSIH1P21A_BTA_TO_CNT_tag_t { + struct _DSIH1P21A_BTA_TO_CNT_map_t + { +volatile unsigned int bta_to_cnt : + 16; //[15:0] + /* + This field sets a period for which the DWC_mipi_dsi_host keeps the + link still, after completing a Bus Turn-Around. This period is measured + in cycles of lanebyteclk. The counting starts when the D-PHY enters + the Stop state and causes no interrupts. + */ +volatile unsigned int reserved_0 : + 16; //[31:16] + } + mBits; + volatile unsigned int dValue; + } + BTA_TO_CNT;// 0x008C + + union _DSIH1P21A_SDF_3D_tag_t { + struct _DSIH1P21A_SDF_3D_map_t + { +volatile unsigned int mode_3d : + 2; //[1:0] + /* + This field defines the 3D mode on/off and display orientation: + 00: 3D mode off (2D mode on) + 01: 3D mode on, portrait orientation + 10: 3D mode on, landscape orientation + 11: Reserved + + */ +volatile unsigned int ormat_3d : + 2; //[3:2] + /* + This field defines the 3D image format: + 00: Line (alternating lines of left and right data) + 01: Frame (alternating frames of left and right data) + 10: Pixel (alternating pixels of left and right data) + 11: Reserved + + */ +volatile unsigned int second_vsync : + 1; //[4] + /* + This field defines whether there is a second VSYNC pulse between + Left and Right Images, when 3D Image Format is Frame-based: + 0: No sync pulses between left and right data + 1: Sync pulse (HSYNC, VSYNC, blanking) between left and right + data + */ +volatile unsigned int right_first : + 1; //[5] + /* + This bit defines the left or right order: + 0: Left eye data is sent first, and then the right eye data is sent. + 1: Right eye data is sent first, and then the left eye data is sent. + */ +volatile unsigned int reserved_0 : + 10; //[15:6] +volatile unsigned int send_3d_cfg : + 1; //[16] + /* + When set, causes the next VSS packet to include 3D control payload + in every VSS packet. + */ +volatile unsigned int reserved_1 : + 15; //[31:17] + } + mBits; + volatile unsigned int dValue; + } + SDF_3D;// 0x0090 + + union _DSIH1P21A_LPCLK_CTRL_tag_t { + struct _DSIH1P21A_LPCLK_CTRL_map_t + { +volatile unsigned int phy_txrequestclkhs : + 1; //[0] This bit controls the D-PHY PPI txrequestclkhs signal +volatile unsigned int auto_clklane_ctrl : + 1; //[0] This bit enables the automatic mechanism to stop providing clock in the clock lane when time allows +volatile unsigned int reserved_0 : + 30; //[31:2] + } + mBits; + volatile unsigned int dValue; + } + LPCLK_CTRL;// 0x0094 + + union _DSIH1P21A_PHY_TMR_LPCLK_CFG_tag_t { + struct _DSIH1P21A_PHY_TMR_LPCLK_CFG_map_t + { +volatile unsigned int phy_clklp2hs_time : + 10; //[9:0] + /* + This field configures the maximum time that the D-PHY clock lane + takes to go from low-power to high-speed transmission measured in + lane byte clock cycles. + */ +volatile unsigned int reserved_0 : + 6; //[15:10] +volatile unsigned int phy_clkhs2lp_time : + 10; //[25:16] + /* + This field configures the maximum time that the D-PHY clock lane + takes to go from high-speed to low-power transmission measured in + lane byte clock cycles. + */ +volatile unsigned int reserved_1 : + 6; //[31:26] + } + mBits; + volatile unsigned int dValue; + } + PHY_TMR_LPCLK_CFG;// 0x0098 + + union _DSIH1P21A_PHY_TMR_CFG_tag_t { + struct _DSIH1P21A_PHY_TMR_CFG_map_t + { +volatile unsigned int max_rd_time : + 15; //[14:0] + /* + This field configures the maximum time required to perform a read + command in lane byte clock cycles. This register can only be modified + when no read command is in progress. + */ +volatile unsigned int reserved_0 : + 1; //[15] +volatile unsigned int phy_lp2hs_time : + 8; //[23:16] + /* + This field configures the maximum time that the D-PHY data lanes + take to go from low-power to high-speed transmission measured in + lane byte clock cycles. + */ +volatile unsigned int phy_hs2lp_time : + 8; //[31:24] + /* + This field configures the maximum time that the D-PHY data lanes + take to go from high-speed to low-power transmission measured in + lane byte clock cycles. + */ + } + mBits; + volatile unsigned int dValue; + } PHY_TMR_CFG;// 0x009C + + union _DSIH1P21A_PHY_RSTZ_tag_t { + struct _DSIH1P21A_PHY_RSTZ_map_t + { +volatile unsigned int phy_shutdownz : + 1; //[0] When set to 0, this bit places the D-PHY macro in power-down state +volatile unsigned int phy_rstz : + 1; //[1] When set to 0, this bit places the digital section of the D-PHY in the reset state. +volatile unsigned int phy_enableclk : + 1; //[2] When set to1, this bit enables the D-PHY Clock Lane module. +volatile unsigned int phy_forcepll : + 1; //[3] + /* + When the D-PHY is in ULPS, this bit enables the D-PHY PLL. + Dependency: DSI_HOST_FPGA = 0. Otherwise, this bit is reserved + */ +volatile unsigned int reserved_0 : + 28; //[31:4] + } + mBits; + volatile unsigned int dValue; + + } PHY_RSTZ;// 0x00A0 + + union _DSIH1P21A_PHY_IF_CFG_tag_t { + struct _DSIH1P21A_PHY_IF_CFG_map_t + { +volatile unsigned int n_lanes : + 2; //[1:0] + /* + This field configures the number of active data lanes: + 00: One data lane (lane 0) + 01: Two data lanes (lanes 0 and 1) + 10: Three data lanes (lanes 0, 1, and 2) + 11: Four data lanes (lanes 0, 1, 2, and 3) + */ +volatile unsigned int reserved_0 : + 6; //[7:2] +volatile unsigned int phy_stop_wait_time : + 8; //[15:8] This field configures the minimum wait period to request a high-speed transmission after the Stop state. +volatile unsigned int reserved_1 : + 16; //[31:16] + } + mBits; + volatile unsigned int dValue; + }PHY_IF_CFG;// 0x00A4 + + union _DSIH1P21A_PHY_ULPS_CTRL_tag_t { + struct _DSIH1P21A_PHY_ULPS_CTRL_map_t + { +volatile unsigned int phy_txrequlpsclk : + 1; //[0] ULPS mode Request on clock lane. +volatile unsigned int phy_txexitulpsclk : + 1; //[1] ULPS mode Exit on clock lane. +volatile unsigned int phy_txrequlpslan : + 1; //[2] ULPS mode Request on all active data lanes. +volatile unsigned int phy_txexitulpslan : + 1; //[3] ULPS mode Exit on all active data lanes. +volatile unsigned int reserved_0 : + 28; //[31:4] + } + mBits; + volatile unsigned int dValue; + } + PHY_ULPS_CTRL;// 0x00A8 + + union _DSIH1P21A_PHY_TX_TRIGGERS_tag_t { + struct _DSIH1P21A_PHY_TX_TRIGGERS_map_t + { +volatile unsigned int phy_tx_triggers : + 4; //[3:0] This field controls the trigger transmissions +volatile unsigned int reserved_0 : + 28; //[31:4] + } + mBits; + volatile unsigned int dValue; + } + PHY_TX_TRIGGERS;// 0x00AC + + union _DSIH1P21A_PHY_STATUS_tag_t { + struct _DSIH1P21A_PHY_STATUS_map_t + { +volatile unsigned int phy_lock : + 1; //[0] This bit indicates the status of phylock D-PHY signal. +volatile unsigned int phy_direction : + 1; //[1] This bit indicates the status of phydirection D-PHY signal. +volatile unsigned int phy_stopstateclklane : + 1; //[2] This bit indicates the status of phystopstateclklane D-PHY signal. +volatile unsigned int phy_ulpsactivenotclk : + 1; //[3] This bit indicates the status of phyulpsactivenotclk D-PHY signal. +volatile unsigned int phy_stopstate0lane : + 1; //[4] This bit indicates the status of phystopstate0lane D-PHY signal. +volatile unsigned int phy_ulpsactivenot0lane : + 1; //[5] This bit indicates the status of ulpsactivenot0lane D-PHY signal. +volatile unsigned int phy_rxulpsesc0lane : + 1; //[6] This bit indicates the status of rxulpsesc0lane D-PHY signal. +volatile unsigned int phy_stopstate1lane : + 1; //[7] + /* + This bit indicates the status of phystopstate1lane D-PHY signal. + Dependency: DSI_HOST_NUMBER_OF_LANES > 1 + If DSI_HOST_NUMBER_OF_LANES <= 1, this bit is reserved. + */ +volatile unsigned int phy_ulpsactivenot1lane : + 1; //[8] + /* + This bit indicates the status of ulpsactivenot1lane D-PHY signal. + Dependency: DSI_HOST_NUMBER_OF_LANES > 1 + If DSI_HOST_NUMBER_OF_LANES <= 1, this bit is reserved. + */ +volatile unsigned int phy_stopstate2lane : + 1; //[9] + /* + This bit indicates the status of phystopstate2lane D-PHY signal. + Dependency: DSI_HOST_NUMBER_OF_LANES > 2 + If DSI_HOST_NUMBER_OF_LANES <= 2, this bit is reserved. + */ +volatile unsigned int phy_ulpsactivenot2lane : + 1; //[10] + /* + This bit indicates the status of ulpsactivenot2lane D-PHY signal. + Dependency: DSI_HOST_NUMBER_OF_LANES > 2 + If DSI_HOST_NUMBER_OF_LANES <= 2, this bit is reserved. + */ +volatile unsigned int phy_stopstate3lane : + 1; //[11] + /* + This bit indicates the status of phystopstate3lane D-PHY signal. + Dependency: DSI_HOST_NUMBER_OF_LANES > 3 + If DSI_HOST_NUMBER_OF_LANES <= 3, this bit is reserved + */ +volatile unsigned int phy_ulpsactivenot3lane : + 1; //[12] + /* + This bit indicates the status of ulpsactivenot3lane D-PHY signal. + Dependency: DSI_HOST_NUMBER_OF_LANES > 3 + If DSI_HOST_NUMBER_OF_LANES <= 3, this bit is reserved + */ +volatile unsigned int reserved_0 : + 19; //[31:13] + } + mBits; + volatile unsigned int dValue; + } PHY_STATUS;// 0x00B0 + + union _DSIH1P21A_PHY_TST_CTRL0_tag_t { + struct _DSIH1P21A_PHY_TST_CTRL0_map_t + { +volatile unsigned int phy_testclr : + 1; //[0] PHY test interface clear (active high). +volatile unsigned int phy_testclk : + 1; //[1] This bit is used to clock the TESTDIN bus into the D-PHY. +volatile unsigned int reserved_0 : + 30; //[31:2] + } + mBits; + volatile unsigned int dValue; + } + PHY_TST_CTRL0;// 0x00B4 + + union _DSIH1P21A_PHY_TST_CTRL1_tag_t { + struct _DSIH1P21A_PHY_TST_CTRL1_map_t + { +volatile unsigned int phy_testdin : + 8; //[7:0] PHY test interface input 8-bit data bus for internal register programming and test functionalities access. +volatile unsigned int pht_testdout : + 8; //[15:8] PHY output 8-bit data bus for read-back and internal probing functionalities. +volatile unsigned int phy_testen : + 1; //[16] + /* + PHY test interface operation selector: + 1: The address write operation is set on the falling edge of the testclk signal. + 0: The data write operation is set on the rising edge of the testclk signal. + */ +volatile unsigned int reserved_0 : + 15; //[31:17] + } + mBits; + volatile unsigned int dValue; + } + PHY_TST_CTRL1;// 0x00B8 + + union _DSIH1P21A_INT_ST0_tag_t { + struct _DSIH1P21A_INT_ST0_map_t + { +volatile unsigned int ack_with_err_0 : + 1; //[0] This bit retrieves the SoT error from the Acknowledge error report. +volatile unsigned int ack_with_err_1 : + 1; //[1] This bit retrieves the SoT Sync error from the Acknowledge error report. +volatile unsigned int ack_with_err_2 : + 1; //[2] This bit retrieves the EoT Sync error from the Acknowledge error report. +volatile unsigned int ack_with_err_3 : + 1; //[3] This bit retrieves the Escape Mode Entry Command error from the Acknowledge error report. +volatile unsigned int ack_with_err_4 : + 1; //[4] This bit retrieves the LP Transmit Sync error from the Acknowledge error report. +volatile unsigned int ack_with_err_5 : + 1; //[5] This bit retrieves the Peripheral Timeout error from the Acknowledge Error report. +volatile unsigned int ack_with_err_6 : + 1; //[6] This bit retrieves the False Control error from the Acknowledge error report. +volatile unsigned int ack_with_err_7 : + 1; //[7] This bit retrieves the reserved (specific to device) from the Acknowledge error report. +volatile unsigned int ack_with_err_8 : + 1; //[8] This bit retrieves the ECC error, single-bit (detected and corrected) from the Acknowledge error report. +volatile unsigned int ack_with_err_9 : + 1; //[9] This bit retrieves the ECC error, multi-bit (detected, not corrected) from the Acknowledge error report. +volatile unsigned int ack_with_err_10 : + 1; //[10]This bit retrieves the checksum error (long packet only) from the Acknowledge error report. +volatile unsigned int ack_with_err_11 : + 1; //[11] This bit retrieves the not recognized DSI data type from the Acknowledge error report. +volatile unsigned int ack_with_err_12 : + 1; //[12] This bit retrieves the DSI VC ID Invalid from the Acknowledge error report. +volatile unsigned int ack_with_err_13 : + 1; //[13] This bit retrieves the invalid transmission length from the Acknowledge error report. +volatile unsigned int ack_with_err_14 : + 1; //[14] This bit retrieves the reserved (specific to device) from the Acknowledge error report +volatile unsigned int ack_with_err_15 : + 1; //[15] This bit retrieves the DSI protocol violation from the Acknowledge error report. +volatile unsigned int dphy_errors_0 : + 1; //[16] This bit indicates ErrEsc escape entry error from Lane 0. +volatile unsigned int dphy_errors_1 : + 1; //[17] This bit indicates ErrSyncEsc low-power data transmission synchronization error from Lane 0. +volatile unsigned int dphy_errors_2 : + 1; //[18] This bit indicates the ErrControl error from Lane 0. +volatile unsigned int dphy_errors_3 : + 1; //[19] This bit indicates the LP0 contention error ErrContentionLP0 from Lane 0. +volatile unsigned int dphy_errors_4 : + 1; //[20] This bit indicates the LP1 contention error ErrContentionLP1 from Lane 0. +volatile unsigned int reserved_0 : + 11; //[31:21] + } + mBits; + volatile unsigned int dValue; + } + INT_ST0;// 0x00BC + + union _DSIH1P21A_INT_ST1_tag_t { + struct _DSIH1P21A_INT_ST1_map_t + { +volatile unsigned int to_hs_tx : + 1; //[0] + /* + This bit indicates that the high-speed transmission timeout counter + reached the end and contention is detected. + */ +volatile unsigned int to_lp_rx : + 1; //[1] + /* + This bit indicates that the low-power reception timeout counter reached + the end and contention is detected. + */ +volatile unsigned int ecc_single_err : + 1; //[2] + /* + This bit indicates that the ECC single error is detected and corrected in a + received packet. + */ +volatile unsigned int ecc_multi_err : + 1; //[3] + /* + This bit indicates that the ECC multiple error is detected in a received + packet. + */ +volatile unsigned int crc_err : + 1; //[4] + /* + This bit indicates that the CRC error is detected in the received packet + payload. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3 or + DSI_GENERIC = 1. Otherwise, this bit is reserved. + */ +volatile unsigned int pkt_size_err : + 1; //[5] + /* + This bit indicates that the packet size error is detected during the packet + reception. + */ +volatile unsigned int eopt_err : + 1; //[6] + /* + This bit indicates that the EoTp packet is not received at the end of the + incoming peripheral transmission + */ +volatile unsigned int dpi_pld_wr_err : + 1; //[7] + /* + This bit indicates that during a DPI pixel line storage, the payload FIFO + becomes full and the data stored is corrupted. + Dependency: DSI_DATAINTERFACE = 2 or DSI_DATAINTERFACE = 3 or + DSI_DATAINTERFACE = 4. Otherwise, this bit is reserved. + */ +volatile unsigned int gen_cmd_wr_err : + 1; //[8] + /* + This bit indicates that the system tried to write a command through the + Generic interface and the FIFO is full. Therefore, the command is not + written. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved + */ +volatile unsigned int gen_pld_wr_err : + 1; //[9] + /* + This bit indicates that the system tried to write a payload data through the + Generic interface and the FIFO is full. Therefore, the payload is not + written. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved + */ +volatile unsigned int gen_pld_send_err : + 1; //[10] + /* + This bit indicates that during a Generic interface packet build, the payload + FIFO becomes empty and corrupt data is sent. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved + */ +volatile unsigned int gen_pld_rd_err : + 1; //[11] + /* + This bit indicates that during a DCS read data, the payload FIFO becomes + empty and the data sent to the interface is corrupted. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved. + */ +volatile unsigned int gen_pld_recev_err : + 1; //[12] + /* + This bit indicates that during a generic interface packet read back, the + payload FIFO becomes full and the received data is corrupted. + Dependency: DSI_GENERIC = 1 + If DSI_GENERIC = 0, this bit is reserved. + */ +volatile unsigned int dbi_cmd_wr_err : + 1; //[13] + /* + This bit indicates that the system tried to write a command through the + DBI but the command FIFO is full. Therefore, the command is not written. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + */ +volatile unsigned int dbi_pld_wr_err : + 1; //[14] + /* + This bit indicates that the system tried to write the payload data through + the DBI interface and the FIFO is full. Therefore, the command is not + written. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + */ +volatile unsigned int dbi_pld_rd_err : + 1; //[15] + /* + This bit indicates that during a DCS read data, the payload FIFO goes + empty and the data sent to the interface is corrupted. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + */ +volatile unsigned int dbi_pld_recv_err : + 1; //[16] + /* + This bit indicates that during a DBI read back packet, the payload FIFO + becomes full and the received data is corrupted. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + */ + +volatile unsigned int dbi_ilegal_comm_err : + 1; //[17] + /* + This bit indicates that an attempt to write an illegal command on the DBI + interface is made and the core is blocked by transmission. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + */ +volatile unsigned int reserved_0 : + 14; //[31:18] + } + mBits; + volatile unsigned int dValue; + } + INT_ST1;// 0x00C0 + + + union _DSIH1P21A_INT_MSK0_tag_t { + struct _DSIH1P21A_INT_MSK0_map_t + { +volatile unsigned int ack_with_err_0 : + 1; //[0] This bit retrieves the SoT error from the Acknowledge error report. +volatile unsigned int ack_with_err_1 : + 1; //[1] This bit retrieves the SoT Sync error from the Acknowledge error report. +volatile unsigned int ack_with_err_2 : + 1; //[2] This bit retrieves the EoT Sync error from the Acknowledge error report. +volatile unsigned int ack_with_err_3 : + 1; //[3] This bit retrieves the Escape Mode Entry Command error from the Acknowledge error report. +volatile unsigned int ack_with_err_4 : + 1; //[4] This bit retrieves the LP Transmit Sync error from the Acknowledge error report. +volatile unsigned int ack_with_err_5 : + 1; //[5] This bit retrieves the Peripheral Timeout error from the Acknowledge Error report. +volatile unsigned int ack_with_err_6 : + 1; //[6] This bit retrieves the False Control error from the Acknowledge error report. +volatile unsigned int ack_with_err_7 : + 1; //[7] This bit retrieves the reserved (specific to device) from the Acknowledge error report. +volatile unsigned int ack_with_err_8 : + 1; //[8] This bit retrieves the ECC error, single-bit (detected and corrected) from the Acknowledge error report. +volatile unsigned int ack_with_err_9 : + 1; //[9] This bit retrieves the ECC error, multi-bit (detected, not corrected) from the Acknowledge error report. +volatile unsigned int ack_with_err_10 : + 1; //[10]This bit retrieves the checksum error (long packet only) from the Acknowledge error report. +volatile unsigned int ack_with_err_11 : + 1; //[11] This bit retrieves the not recognized DSI data type from the Acknowledge error report. +volatile unsigned int ack_with_err_12 : + 1; //[12] This bit retrieves the DSI VC ID Invalid from the Acknowledge error report. +volatile unsigned int ack_with_err_13 : + 1; //[13] This bit retrieves the invalid transmission length from the Acknowledge error report. +volatile unsigned int ack_with_err_14 : + 1; //[14] This bit retrieves the reserved (specific to device) from the Acknowledge error report +volatile unsigned int ack_with_err_15 : + 1; //[15] This bit retrieves the DSI protocol violation from the Acknowledge error report. +volatile unsigned int dphy_errors_0 : + 1; //[16] This bit indicates ErrEsc escape entry error from Lane 0. +volatile unsigned int dphy_errors_1 : + 1; //[17] This bit indicates ErrSyncEsc low-power data transmission synchronization error from Lane 0. +volatile unsigned int dphy_errors_2 : + 1; //[18] This bit indicates the ErrControl error from Lane 0. +volatile unsigned int dphy_errors_3 : + 1; //[19] This bit indicates the LP0 contention error ErrContentionLP0 from Lane 0. +volatile unsigned int dphy_errors_4 : + 1; //[20] This bit indicates the LP1 contention error ErrContentionLP1 from Lane 0. +volatile unsigned int reserved_0 : + 11; //[31:21] + } + mBits; + volatile unsigned int dValue; + } + INT_MSK0;// 0x00C4 + + + union _DSIH1P21A_INT_MSK1_tag_t { + struct _DSIH1P21A_INT_MSK1_map_t + { +volatile unsigned int to_hs_tx : + 1; //[0] + /* + This bit indicates that the high-speed transmission timeout counter + reached the end and contention is detected. + */ +volatile unsigned int to_lp_rx : + 1; //[1] + /* + This bit indicates that the low-power reception timeout counter reached + the end and contention is detected. + */ +volatile unsigned int ecc_single_err : + 1; //[2] + /* + This bit indicates that the ECC single error is detected and corrected in a + received packet. + */ +volatile unsigned int ecc_multi_err : + 1; //[3] + /* + This bit indicates that the ECC multiple error is detected in a received + packet. + */ +volatile unsigned int crc_err : + 1; //[4] + /* + This bit indicates that the CRC error is detected in the received packet + payload. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3 or + DSI_GENERIC = 1. Otherwise, this bit is reserved. + */ +volatile unsigned int pkt_size_err : + 1; //[5] + /* + This bit indicates that the packet size error is detected during the packet + reception. + */ +volatile unsigned int eopt_err : + 1; //[6] + /* + This bit indicates that the EoTp packet is not received at the end of the + incoming peripheral transmission + */ +volatile unsigned int dpi_pld_wr_err : + 1; //[7] + /* + This bit indicates that during a DPI pixel line storage, the payload FIFO + becomes full and the data stored is corrupted. + Dependency: DSI_DATAINTERFACE = 2 or DSI_DATAINTERFACE = 3 or + DSI_DATAINTERFACE = 4. Otherwise, this bit is reserved. + */ +volatile unsigned int gen_cmd_wr_err : + 1; //[8] + /* + This bit indicates that the system tried to write a command through the + Generic interface and the FIFO is full. Therefore, the command is not + written. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved + */ +volatile unsigned int gen_pld_wr_err : + 1; //[9] + /* + This bit indicates that the system tried to write a payload data through the + Generic interface and the FIFO is full. Therefore, the payload is not + written. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved + */ +volatile unsigned int gen_pld_send_err : + 1; //[10] + /* + This bit indicates that during a Generic interface packet build, the payload + FIFO becomes empty and corrupt data is sent. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved + */ +volatile unsigned int gen_pld_rd_err : + 1; //[11] + /* + This bit indicates that during a DCS read data, the payload FIFO becomes + empty and the data sent to the interface is corrupted. + Dependency: DSI_GENERIC = 1. Otherwise, this bit is reserved. + */ +volatile unsigned int gen_pld_recev_err : + 1; //[12] + /* + This bit indicates that during a generic interface packet read back, the + payload FIFO becomes full and the received data is corrupted. + Dependency: DSI_GENERIC = 1 + If DSI_GENERIC = 0, this bit is reserved. + */ +volatile unsigned int dbi_cmd_wr_err : + 1; //[13] + /* + This bit indicates that the system tried to write a command through the + DBI but the command FIFO is full. Therefore, the command is not written. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + */ +volatile unsigned int dbi_pld_wr_err : + 1; //[14] + /* + This bit indicates that the system tried to write the payload data through + the DBI interface and the FIFO is full. Therefore, the command is not + written. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + */ +volatile unsigned int dbi_pld_rd_err : + 1; //[15] + /* + This bit indicates that during a DCS read data, the payload FIFO goes + empty and the data sent to the interface is corrupted. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + */ +volatile unsigned int dbi_pld_recv_err : + 1; //[16] + /* + This bit indicates that during a DBI read back packet, the payload FIFO + becomes full and the received data is corrupted. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + */ + +volatile unsigned int dbi_ilegal_comm_err : + 1; //[17] + /* + This bit indicates that an attempt to write an illegal command on the DBI + interface is made and the core is blocked by transmission. + Dependency: DSI_DATAINTERFACE = 1 or DSI_DATAINTERFACE = 3. + Otherwise, this bit is reserved. + */ +volatile unsigned int reserved_0 : + 14; //[31:18] + } + mBits; + volatile unsigned int dValue; + } + INT_MSK1;// 0x00C8 +}DSIH1P21A_REG_T; + +uint32_t mipi_dsih_hal_get_version(dsih_ctrl_t * instance); + +void mipi_dsih_hal_power(dsih_ctrl_t * instance, int on); + +int mipi_dsih_hal_get_power(dsih_ctrl_t * instance); + +void mipi_dsih_hal_tx_escape_division(dsih_ctrl_t * instance, uint8_t tx_escape_division); + +void mipi_dsih_hal_dpi_video_vc(dsih_ctrl_t * instance, uint8_t vc); + +uint8_t mipi_dsih_hal_dpi_get_video_vc(dsih_ctrl_t * instance); + +dsih_error_t mipi_dsih_hal_dpi_color_coding(dsih_ctrl_t * instance, dsih_color_coding_t color_coding); +dsih_color_coding_t mipi_dsih_hal_dpi_get_color_coding(dsih_ctrl_t * instance); +uint8_t mipi_dsih_hal_dpi_get_color_depth(dsih_ctrl_t * instance); +uint8_t mipi_dsih_hal_dpi_get_color_config(dsih_ctrl_t * instance); +void mipi_dsih_hal_dpi_18_loosely_packet_en(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dpi_color_mode_pol(dsih_ctrl_t * instance, int active_low); +void mipi_dsih_hal_dpi_shut_down_pol(dsih_ctrl_t * instance, int active_low); +void mipi_dsih_hal_dpi_hsync_pol(dsih_ctrl_t * instance, int active_low); +void mipi_dsih_hal_dpi_vsync_pol(dsih_ctrl_t * instance, int active_low); +void mipi_dsih_hal_dpi_dataen_pol(dsih_ctrl_t * instance, int active_low); +void mipi_dsih_hal_dpi_frame_ack_en(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dpi_null_packet_en(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dpi_multi_packet_en(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dpi_lp_during_hfp(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dpi_lp_during_hbp(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dpi_lp_during_vactive(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dpi_lp_during_vfp(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dpi_lp_during_vbp(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dpi_lp_during_vsync(dsih_ctrl_t * instance, int enable); + +dsih_error_t mipi_dsih_hal_dpi_video_mode_type(dsih_ctrl_t * instance, dsih_video_mode_t type); +void mipi_dsih_hal_dpi_video_mode_en(dsih_ctrl_t * instance, int enable); +int mipi_dsih_hal_dpi_is_video_mode(dsih_ctrl_t * instance); +dsih_error_t mipi_dsih_hal_dpi_null_packet_size(dsih_ctrl_t * instance, uint16_t size); +dsih_error_t mipi_dsih_hal_dpi_chunks_no(dsih_ctrl_t * instance, uint16_t no); +dsih_error_t mipi_dsih_hal_dpi_video_packet_size(dsih_ctrl_t * instance, uint16_t size); + +void mipi_dsih_hal_tear_effect_ack_en(dsih_ctrl_t * instance, int enable); + +void mipi_dsih_hal_cmd_ack_en(dsih_ctrl_t * instance, int enable); +dsih_error_t mipi_dsih_hal_dcs_wr_tx_type(dsih_ctrl_t * instance, unsigned no_of_param, int lp); +dsih_error_t mipi_dsih_hal_dcs_rd_tx_type(dsih_ctrl_t * instance, unsigned no_of_param, int lp); +/*Jessica add to support max rd packet size command*/ +dsih_error_t mipi_dsih_hal_max_rd_packet_size_type(dsih_ctrl_t * instance, int lp); +dsih_error_t mipi_dsih_hal_gen_wr_tx_type(dsih_ctrl_t * instance, unsigned no_of_param, int lp); +dsih_error_t mipi_dsih_hal_gen_rd_tx_type(dsih_ctrl_t * instance, unsigned no_of_param, int lp); +void mipi_dsih_hal_max_rd_size_type(dsih_ctrl_t * instance, int lp); +void mipi_dsih_hal_gen_cmd_mode_en(dsih_ctrl_t * instance, int enable); +int mipi_dsih_hal_gen_is_cmd_mode(dsih_ctrl_t * instance); + +void mipi_dsih_hal_dpi_hline(dsih_ctrl_t * instance, uint16_t time); +void mipi_dsih_hal_dpi_hbp(dsih_ctrl_t * instance, uint16_t time); +void mipi_dsih_hal_dpi_hsa(dsih_ctrl_t * instance, uint16_t time); +void mipi_dsih_hal_dpi_vactive(dsih_ctrl_t * instance, uint16_t lines); +void mipi_dsih_hal_dpi_vfp(dsih_ctrl_t * instance, uint16_t lines); +void mipi_dsih_hal_dpi_vbp(dsih_ctrl_t * instance, uint16_t lines); +void mipi_dsih_hal_dpi_vsync(dsih_ctrl_t * instance, uint16_t lines); + +void mipi_dsih_hal_edpi_max_allowed_size(dsih_ctrl_t * instance, uint16_t size); + +dsih_error_t mipi_dsih_hal_gen_packet_header(dsih_ctrl_t * instance, uint8_t vc, uint8_t packet_type, uint8_t ms_byte, uint8_t ls_byte); +dsih_error_t mipi_dsih_hal_gen_packet_payload(dsih_ctrl_t * instance, uint32_t payload); +dsih_error_t mipi_dsih_hal_gen_read_payload(dsih_ctrl_t * instance, uint32_t* payload); + +void mipi_dsih_hal_timeout_clock_division(dsih_ctrl_t * instance, uint8_t byte_clk_division_factor); +void mipi_dsih_hal_lp_rx_timeout(dsih_ctrl_t * instance, uint16_t count); +void mipi_dsih_hal_hs_tx_timeout(dsih_ctrl_t * instance, uint16_t count); + +uint32_t mipi_dsih_hal_int_status_0(dsih_ctrl_t * instance, uint32_t mask); +uint32_t mipi_dsih_hal_int_status_1(dsih_ctrl_t * instance, uint32_t mask); +void mipi_dsih_hal_int_mask_0(dsih_ctrl_t * instance, uint32_t mask); +void mipi_dsih_hal_int_mask_1(dsih_ctrl_t * instance, uint32_t mask); +uint32_t mipi_dsih_hal_int_get_mask_0(dsih_ctrl_t * instance, uint32_t mask); +uint32_t mipi_dsih_hal_int_get_mask_1(dsih_ctrl_t * instance, uint32_t mask); +/* DBI command interface */ +void mipi_dsih_hal_dbi_out_color_coding(dsih_ctrl_t * instance, uint8_t color_depth, uint8_t option); +void mipi_dsih_hal_dbi_in_color_coding(dsih_ctrl_t * instance, uint8_t color_depth, uint8_t option); +void mipi_dsih_hal_dbi_lut_size(dsih_ctrl_t * instance, uint8_t size); +void mipi_dsih_hal_dbi_partitioning_en(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_dbi_dcs_vc(dsih_ctrl_t * instance, uint8_t vc); + +void mipi_dsih_hal_dbi_cmd_size(dsih_ctrl_t * instance, uint16_t size); +void mipi_dsih_hal_dbi_max_cmd_size(dsih_ctrl_t * instance, uint16_t size); +int mipi_dsih_hal_dbi_rd_cmd_busy(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_read_fifo_full(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_read_fifo_empty(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_write_fifo_full(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_write_fifo_empty(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_cmd_fifo_full(dsih_ctrl_t * instance); +int mipi_dsih_hal_dbi_cmd_fifo_empty(dsih_ctrl_t * instance); +/* Generic command interface */ +void mipi_dsih_hal_gen_rd_vc(dsih_ctrl_t * instance, uint8_t vc); +void mipi_dsih_hal_gen_eotp_rx_en(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_gen_eotp_tx_en(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_bta_en(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_gen_ecc_rx_en(dsih_ctrl_t * instance, int enable); +void mipi_dsih_hal_gen_crc_rx_en(dsih_ctrl_t * instance, int enable); +int mipi_dsih_hal_gen_rd_cmd_busy(dsih_ctrl_t * instance); +int mipi_dsih_hal_gen_read_fifo_full(dsih_ctrl_t * instance); +int mipi_dsih_hal_gen_read_fifo_empty(dsih_ctrl_t * instance); +int mipi_dsih_hal_gen_write_fifo_full(dsih_ctrl_t * instance); +int mipi_dsih_hal_gen_write_fifo_empty(dsih_ctrl_t * instance); +int mipi_dsih_hal_gen_cmd_fifo_full(dsih_ctrl_t * instance); +int mipi_dsih_hal_gen_cmd_fifo_empty(dsih_ctrl_t * instance); + +/* only if DPI */ +dsih_error_t mipi_dsih_phy_hs2lp_config(dsih_ctrl_t * instance, uint8_t no_of_byte_cycles); +dsih_error_t mipi_dsih_phy_lp2hs_config(dsih_ctrl_t * instance, uint8_t no_of_byte_cycles); +dsih_error_t mipi_dsih_phy_clk_lp2hs_config(dsih_ctrl_t * instance, uint8_t no_of_byte_cycles); +dsih_error_t mipi_dsih_phy_clk_hs2lp_config(dsih_ctrl_t * instance, uint8_t no_of_byte_cycles); +dsih_error_t mipi_dsih_phy_bta_time(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); +void mipi_dsih_non_continuous_clock(dsih_ctrl_t * instance, int enable); +int mipi_dsih_non_continuous_clock_status(dsih_ctrl_t * instance); +/* PRESP Time outs */ +void mipi_dsih_hal_presp_timeout_low_power_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); +void mipi_dsih_hal_presp_timeout_low_power_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); +void mipi_dsih_hal_presp_timeout_high_speed_write(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); +void mipi_dsih_hal_presp_timeout_high_speed_read(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); +void mipi_dsih_hal_presp_timeout_bta(dsih_ctrl_t * instance, uint16_t no_of_byte_cycles); +/* bsp abstraction */ +void mipi_dsih_write_word(dsih_ctrl_t * instance, uint32_t reg_address, uint32_t data); +void mipi_dsih_write_part(dsih_ctrl_t * instance, uint32_t reg_address, uint32_t data, uint8_t shift, uint8_t width); +uint32_t mipi_dsih_read_word(dsih_ctrl_t * instance, uint32_t reg_address); +uint32_t mipi_dsih_read_part(dsih_ctrl_t * instance, uint32_t reg_address, uint8_t shift, uint8_t width); + +#endif /* MIPI_DSI_API_H_ */ diff --git a/drivers/autotst/mipi_dsih_local.h b/drivers/autotst/mipi_dsih_local.h new file mode 100644 index 00000000..a2d98944 --- /dev/null +++ b/drivers/autotst/mipi_dsih_local.h @@ -0,0 +1,362 @@ +/** + * @file mipi_dsih_local.h + * @brief instance context structure and enumerator definitions: + * errors, events, color coding, video modes and driver state + * + * Synopsys Inc. + * SG DWC PT02 + */ +/* + The Synopsys Software Driver and documentation (hereinafter "Software") + is an unsupported proprietary work of Synopsys, Inc. unless otherwise + expressly agreed to in writing between Synopsys and you. + + The Software IS NOT an item of Licensed Software or Licensed Product under + any End User Software License Agreement or Agreement for Licensed Product + with Synopsys or any supplement thereto. Permission is hereby granted, + free of charge, to any person obtaining a copy of this software annotated + with this license and the Software, to deal in the Software without + restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject + to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + */ + +#ifndef MIPI_DSIH_LOCAL_H_ +#define MIPI_DSIH_LOCAL_H_ + +//#include +#include + + +#define FB_DSIH_VERSION_1P21A + +#define SPRD_MIPI_DPHY_GEN2 + +//typedef unsigned char uint8_t; +//typedef unsigned short uint16_t; +//typedef unsigned int uint32_t; + +#define DSIH_PIXEL_TOLERANCE (2) +#define DSIH_FIFO_ACTIVE_WAIT (5000) /* no of tries to access the fifo */ +#define DSIH_PHY_ACTIVE_WAIT (50000) +#define ONE_MS_ACTIVE_WAIT (50000) /* 50MHz processor */ +#define DEFAULT_BYTE_CLOCK (432000) /* a value to start PHY PLL - random */ +#define MAX_NULL_SIZE (1023) +#define FIFO_DEPTH (1096) +#define WORD_LENGTH (4) /* bytes (32bit registers) */ + +/** Define D-PHY type */ + +#ifdef SPRD_MIPI_DPHY_GEN1 +/** DWC_MIPI_DPHY_BIDIR_TSMC40LP 4 Lanes Gen 1 1GHz */ +#define DWC_MIPI_DPHY_BIDIR_TSMC40LP +#endif +#ifdef SPRD_MIPI_DPHY_GEN2 +/** DWC_MIPI_DPHY_BIDIR_TSMC40LP / GF28LP 4 Lanes Gen 2 1.5GHz */ +#define GEN_2 +#endif +/** 4 Lanes Gen 2 1.5GHz testchips */ +//#define TESTCHIP +/** TQL 2 Lane test chip */ +/* #define DPHY2Btql */ + +/** + * Errors generated by the DSI Host controller driver + */ +typedef enum +{ + OK = 0, + ERR_DSI_COLOR_CODING, + ERR_DSI_OUT_OF_BOUND, + ERR_DSI_OVERFLOW, + ERR_DSI_INVALID_INSTANCE, + ERR_DSI_INVALID_IO, + ERR_DSI_CORE_INCOMPATIBLE, + ERR_DSI_VIDEO_MODE, + ERR_DSI_INVALID_COMMAND, + ERR_DSI_INVALID_EVENT, + ERR_DSI_INVALID_HANDLE, + ERR_DSI_PHY_POWERUP, + ERR_DSI_PHY_INVALID, + ERR_DSI_PHY_FREQ_OUT_OF_BOUND, +//#ifdef GEN_2 + ERR_DSI_PHY_PLL_NOT_LOCKED, +//#endif + ERR_DSI_TIMEOUT +} +dsih_error_t; +/** + * Video stream type + */ +typedef enum +{ + VIDEO_NON_BURST_WITH_SYNC_PULSES = 0, + VIDEO_NON_BURST_WITH_SYNC_EVENTS, + VIDEO_BURST_WITH_SYNC_PULSES +} +dsih_video_mode_t; +/** + * Color coding type (depth and pixel configuration) + */ +typedef enum +{ + COLOR_CODE_16BIT_CONFIG1 = 0, + COLOR_CODE_16BIT_CONFIG2 = 1, + COLOR_CODE_16BIT_CONFIG3 = 2, + COLOR_CODE_18BIT_CONFIG1 = 3, + COLOR_CODE_18BIT_CONFIG2 = 4, + COLOR_CODE_24BIT = 5, + COLOR_CODE_20BIT_YCC422_LOOSELY = 6, + COLOR_CODE_24BIT_YCC422 = 7, + COLOR_CODE_16BIT_YCC422 = 8, + COLOR_CODE_30BIT = 9, + COLOR_CODE_36BIT = 10, + COLOR_CODE_12BIT_YCC420 = 11, + COLOR_CODE_MAX +} +dsih_color_coding_t; +/** + * Events generated by the DSI Host controller + */ +typedef enum +{ + ACK_SOT_ERR = 0, + ACK_SOT_SYNC, + ACK_EOT_SYNC, + ACK_ESCAPE_CMD_ERR, + ACK_LP_TX_SYNC_ERR, + ACK_HS_RX_TIMEOUT_ERR, + ACK_FALSE_CONTROL_ERR, + ACK_RSVD_DEVICE_ERR_7, + ACK_ECC_SINGLE_BIT_ERR, + ACK_ECC_MULTI_BIT_ERR, + ACK_CHECKSUM_ERR, + ACK_DSI_TYPE_NOT_RECOGNIZED_ERR, + ACK_VC_ID_INVALID_ERR, + ACK_INVALID_TX_LENGTH_ERR, + ACK_RSVD_DEVICE_ERR_14, + ACK_DSI_PROTOCOL_ERR, + + DPHY_ESC_ENTRY_ERR, + DPHY_SYNC_ESC_LP_ERR, + DPHY_CONTROL_LANE0_ERR, + DPHY_CONTENTION_LP0_ERR, + DPHY_CONTENTION_LP1_ERR, + /* start of st1 */ + HS_CONTENTION, + LP_CONTENTION, + RX_ECC_SINGLE_ERR, + RX_ECC_MULTI_ERR, + RX_CRC_ERR, + RX_PKT_SIZE_ERR, + RX_EOTP_ERR, + DPI_PLD_FIFO_FULL_ERR, + GEN_TX_CMD_FIFO_FULL_ERR, + GEN_TX_PLD_FIFO_FULL_ERR, + GEN_TX_PLD_FIFO_EMPTY_ERR, + GEN_RX_PLD_FIFO_EMPTY_ERR, + GEN_RX_PLD_FIFO_FULL_ERR, + + DBI_TX_CMD_FIFO_FULL_ERR, + DBI_TX_PLD_FIFO_FULL_ERR, + DBI_RX_PLD_FIFO_EMPTY_ERR, + DBI_RX_PLD_FIFO_FULL_ERR, + DBI_ILLEGAL_CMD_ERR, + DSI_MAX_EVENT +} +dsih_event_t; +/** + * DSI Host state machine states + * Holds the mapping of D-PHY to the OS, logging I/O, and hardware access layer. + */ +typedef enum +{ + NOT_INITIALIZED = 0, + INITIALIZED, + ON, + OFF +} +dsih_state_t; + +/** + * MIPI D-PHY + * Holds the mapping of API to the OS, logging I/O, and hardware access layer + * and HW module information. + */ +typedef struct dphy_t +{ + /** Physical base address of PHY module - REQUIRED */ + uint32_t address; + /** Reference frequency provided to PHY module [KHz] - REQUIRED */ + uint32_t reference_freq; +#ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING + /** mark if D-PHY should keep work or not */ + uint32_t phy_keep_work; +#endif + /** D-PHY driver state - used internally by driver */ + dsih_state_t status; + /** Function handle of any board function that needs to be called + * in order to set up the environment for the D-PHY before it is + * configured. */ + void (*bsp_pre_config)(struct dphy_t *instance, void* param); + /** Register read access function handle - REQUIRED */ + uint32_t (*core_read_function)(uint32_t addr, uint32_t offset); + /** Register write access function handle - REQUIRED */ + void (*core_write_function)(uint32_t addr, uint32_t offset, uint32_t data); + /** Log errors function handle */ + void (*log_error)(const char * string); + /** Log information function handle */ + void (*log_info)(const char *fmt, ...); +} +dphy_t; + +/** + * MIPI DSI Host Controller + * Holds important information for the functioning of the DSI Host Controller API + * Holds the mapping of API to the OS, logging I/O, and hardware access layer. + * It also holds important information set by the user about the HW considerations + * and internal state variables. + */ +typedef struct dsih_ctrl_t +{ + /** Physical base address of controller - REQUIRED */ + uint32_t address; + /** D-PHY instance associated with the DSI host controller - REQUIRED */ + dphy_t phy_instance; + /** Number of lanes physically connected to controller - REQUIRED */ + uint8_t max_lanes; + /** Maximum number of byte clock cycles needed by the PHY to perform + * the Bus Turn Around operation - REQUIRED */ + uint16_t max_bta_cycles; + /** Describe the color mode pin (dpicolorm) whether it is active high or low - REQUIRED */ + int color_mode_polarity; + /** Describe the shut down pin (dpishutdn) whether it is active high or low - REQUIRED */ + int shut_down_polarity; + /** initialised or not */ + dsih_state_t status; + /** Register read access function handle - REQUIRED */ + uint32_t (*core_read_function)(uint32_t addr, uint32_t offset); + /** Register write access function handle - REQUIRED */ + void (*core_write_function)(uint32_t addr, uint32_t offset, uint32_t data); + /** Log errors function handle */ + void (*log_error)(const char * string); + /** Log information function handle */ + void (*log_info)(const char *fmt, ...); + /** Event registry holds handlers of the callbacks of registered events */ + void (*event_registry[DSI_MAX_EVENT])(struct dsih_ctrl_t *instance, void *handler); +} +dsih_ctrl_t; +/** + * Video configurations + * Holds information about the video stream to be sent through the DPI interface. + */ +typedef struct +{ + /** Number of lanes used to send current video */ + uint8_t no_of_lanes; + /** Virtual channel number to send this video stream */ + uint8_t virtual_channel; + /** Video mode, whether burst with sync pulses, or packets with either sync pulses or events */ + dsih_video_mode_t video_mode; + /** Maximum number of byte clock cycles needed by the PHY to transition + * the data lanes from high speed to low power - REQUIRED */ + uint8_t max_hs_to_lp_cycles; + /** Maximum number of byte clock cycles needed by the PHY to transition + * the data lanes from low power to high speed - REQUIRED */ + uint8_t max_lp_to_hs_cycles; + /** Maximum number of byte clock cycles needed by the PHY to transition + * the clock lane from high speed to low power - REQUIRED */ + uint8_t max_clk_hs_to_lp_cycles; + /** Maximum number of byte clock cycles needed by the PHY to transition + * the clock lane from low power to high speed - REQUIRED */ + uint8_t max_clk_lp_to_hs_cycles; + /** Enable non coninuous clock for energy saving + * - Clock lane will go to LS while not transmitting video */ + int non_continuous_clock; + /** Enable receiving of ack packets */ + int receive_ack_packets; + /** Byte (lane) clock [KHz] */ + uint32_t byte_clock; + /** Pixel (DPI) Clock [KHz]*/ + uint32_t pixel_clock; + /** Colour coding - BPP and Pixel configuration */ + dsih_color_coding_t color_coding; + /** Is 18-bit loosely packets (valid only when BPP == 18) */ + int is_18_loosely; + /** Data enable signal (dpidaten) whether it is active high or low */ + int data_en_polarity; + /** Horizontal synchronisation signal (dpihsync) whether it is active high or low */ + int h_polarity; + /** Horizontal resolution or Active Pixels */ + uint16_t h_active_pixels; /* hadr */ + /** Horizontal Sync Pixels - min 4 for best performance */ + uint16_t h_sync_pixels; + /** Horizontal back porch pixels */ + uint16_t h_back_porch_pixels; /* hbp */ + /** Total Horizontal pixels */ + uint16_t h_total_pixels; /* h_total */ + /** Vertical synchronisation signal (dpivsync) whether it is active high or low */ + int v_polarity; + /** Vertical active lines (resolution) */ + uint16_t v_active_lines; /* vadr */ + /** Vertical sync lines */ + uint16_t v_sync_lines; + /** Vertical back porch lines */ + uint16_t v_back_porch_lines; /* vbp */ + /** Total no of vertical lines */ + uint16_t v_total_lines; /* v_total */ +} +dsih_dpi_video_t; + +typedef struct +{ + /** virtual channel */ + uint8_t virtual_channel; + /** Commands to be sent in high speed or low power */ + int lp; + /** Colour coding - BPP and Pixel configuration */ + dsih_color_coding_t color_coding; + /** Top horizontal pixel position in the display */ + uint16_t h_start; + /** Horizontal resolution or Active Pixels */ + uint16_t h_active_pixels; /* hadr */ + /** Left most line position in the display */ + uint16_t v_start; + /** Vertical active lines (resolution) */ + uint16_t v_active_lines; /* vadr */ + /** Whether Tearing effect should be requested */ + int te; + /** packet size of write memory command - + * 0 is default (optimum usage of RAM) */ + uint16_t packet_size; +} +dsih_cmd_mode_video_t; +/** + * Register configurations + */ +typedef struct +{ + /** Register offset */ + uint32_t addr; + /** Register data [in or out] */ + uint32_t data; +} +register_config_t; + +#endif /* MIPI_DSIH_LOCAL_H_ */ diff --git a/drivers/autotst/pinmap_gpio.h b/drivers/autotst/pinmap_gpio.h new file mode 100644 index 00000000..7f761582 --- /dev/null +++ b/drivers/autotst/pinmap_gpio.h @@ -0,0 +1,116 @@ + +#ifndef _PINMAP_GPIO_20130207_H__ +#define _PINMAP_GPIO_20130207_H__ + +#include +#include +#include +#include +#include + +//LCD +#define gpio101 REG_PIN_LCD_CSN1 +#define gpio102 REG_PIN_LCD_CSN0 +#define gpio103 REG_PIN_LCD_RSTN +#define gpio105 REG_PIN_LCD_FMARK + +//CAM +#define gpio173 REG_PIN_CCIRMCLK +#define gpio186 REG_PIN_CCIRRST +#define gpio187 REG_PIN_CCIRPD1 +#define gpio188 REG_PIN_CCIRPD0 + +#define gpio189 REG_PIN_SCL0 +#define gpio190 REG_PIN_SDA0 +#define gpio236 REG_PIN_TRACEDAT4 + +//CTP&KEYPAD +#define gpio73 REG_PIN_SCL1 +#define gpio74 REG_PIN_SDA1 +#define gpio81 REG_PIN_SIMCLK2 +#define gpio82 REG_PIN_SIMDA2 +#define gpio191 REG_PIN_KEYOUT0 +#define gpio192 REG_PIN_KEYOUT1 +#define gpio193 REG_PIN_KEYOUT2 +#define gpio199 REG_PIN_KEYIN0 +#define gpio200 REG_PIN_KEYIN1 +#define gpio201 REG_PIN_KEYIN2 + +//SIM +#define gpio75 REG_PIN_SIMCLK0 +#define gpio76 REG_PIN_SIMDA0 +#define gpio77 REG_PIN_SIMRST0 +#define gpio78 REG_PIN_SIMCLK1 +#define gpio79 REG_PIN_SIMDA1 +#define gpio80 REG_PIN_SIMRST1 + +//TCARD +#define gpio94 REG_PIN_SD0_CLK0 +#define gpio95 REG_PIN_SD0_CLK1 +#define gpio96 REG_PIN_SD0_CMD +#define gpio97 REG_PIN_SD0_D0 +#define gpio98 REG_PIN_SD0_D1 +#define gpio99 REG_PIN_SD0_D2 +#define gpio100 REG_PIN_SD0_D3 +#define gpio71 REG_PIN_EXTINT0 + +// + +typedef struct { + int num; + uint32_t reg; +} pinmap_gpio_t; + +pinmap_gpio_t pinmap_gpio[] = { +//LCD +{101, gpio101,}, +{102, gpio102,}, +{103, gpio103,}, +{105, gpio105,}, + +//CAM +{173, gpio173,}, +{186, gpio186,}, +{187, gpio187,}, +{188, gpio188,}, +{189, gpio189,}, +{190, gpio190,}, +{236, gpio236,}, + +//CTP +{73, gpio73,}, +{74, gpio74,}, + +{81, gpio81,}, +{82, gpio82,}, +{191, gpio191,}, +{192, gpio192,}, +{193, gpio193,}, +{199, gpio199,}, +{200, gpio200,}, +{201, gpio201,}, + +//SIM +{75, gpio75,}, +{76, gpio76,}, +{77, gpio77,}, +{78, gpio78,}, +{79, gpio79,}, +{80, gpio80,}, + +//TCARD +{94, gpio94,}, +{95, gpio95,}, +{96, gpio96,}, +{97, gpio97,}, +{98, gpio98,}, +{99, gpio99,}, +{100, gpio100,}, +{71, gpio71,}, +}; +struct regulator *autotest_regulator = NULL; + +#define ANA_REG_BIC(_r, _b) sci_adi_write(_r, 0, _b) + + +#endif // _PINMAP_GPIO_20130207_H__ -- cgit v1.3.1