821 lines
25 KiB
C
821 lines
25 KiB
C
/*
|
|
* KDP LCM Display driver
|
|
*
|
|
* Copyright (C) 2019 Kneron, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
|
|
#include <string.h>
|
|
#include "board.h"
|
|
#include "kdrv_gdma.h"
|
|
#include "kdrv_scu_ext.h"
|
|
#include "kdrv_lcm.h"
|
|
#include "kdrv_pwm.h"
|
|
#include "kdrv_clock.h"
|
|
#include "kmdw_memory.h"
|
|
#include "kmdw_display.h"
|
|
//#include "kmdw_console.h"
|
|
#include <framework/mutex.h>
|
|
#include "kl520_include.h"
|
|
|
|
|
|
//#define LCM_DBG
|
|
#ifdef LCM_DBG
|
|
#define lcm_msg(fmt, ...) info_msg("[KDRV_LCM] " fmt, ##__VA_ARGS__)
|
|
#else
|
|
#define lcm_msg(fmt, ...)
|
|
#endif
|
|
|
|
/*=============================== LCM Register Releated Macros ===============================*/
|
|
#define LCM_BASE SLCD_FTLCDC210_PA_BASE
|
|
|
|
#define LCM_REG_TIMING (LCM_BASE + 0x200)
|
|
#define LCM_REG_RDY (LCM_BASE + 0x204)
|
|
#define LCM_REG_RS (LCM_BASE + 0x208)
|
|
#define LCM_REG_DATA (LCM_BASE + 0x20C)
|
|
#define LCM_REG_CMD (LCM_BASE + 0x210)
|
|
#define LCM_REG_OP_MODE (LCM_BASE + 0x214)
|
|
#define LCM_REG_ENABLE (LCM_BASE + 0x228)
|
|
|
|
#define LCM_REG_TIMING_P(base) (base + 0x200)
|
|
#define LCM_REG_RDY_P(base) (base + 0x204)
|
|
#define LCM_REG_RS_P(base) (base + 0x208)
|
|
#define LCM_REG_DATA_P(base) (base + 0x20C)
|
|
#define LCM_REG_CMD_P(base) (base + 0x210)
|
|
#define LCM_REG_OP_MODE_P(base) (base + 0x214)
|
|
#define LCM_REG_ENABLE_P(base) (base + 0x228)
|
|
|
|
/* LCM Timing Control Register, LCM_TIMING (Offset 0x200) */
|
|
#define LCM_REG_TPWH_WIDTH_4_READ_CYCLE() GET_BITS(LCM_REG_TIMING, 16, 19)
|
|
#define LCM_REG_TAS_WIDTH() GET_BITS(LCM_REG_TIMING, 12, 15)
|
|
#define LCM_REG_TAH_WIDTH() GET_BITS(LCM_REG_TIMING, 8, 11)
|
|
#define LCM_REG_TPWL_WIDTH() GET_BITS(LCM_REG_TIMING, 4, 7)
|
|
#define LCM_REG_TPWH_WIDTH_4_WRITE_CYCLE() GET_BITS(LCM_REG_TIMING, 0, 3)
|
|
|
|
/* LCM Ready Register, LCM_RDY (Offset 0x204) */
|
|
#define LCM_REG_LCM_RDY() GET_BIT(LCM_REG_RDY, 0)
|
|
|
|
/* LCM Data Window, LCM_DATA (Offset 0x20C) */
|
|
#define LCM_REG_LCM_DATA() GET_BITS(LCM_REG_DATA, 0, 31)
|
|
|
|
/* LCM Command Register, LCM_CMD (Offset 0x210) */
|
|
#define LCM_REG_LCM_CMD() GET_BITS(LCM_REG_CMD, 0, 31)
|
|
|
|
/* LCM Operation Mode Select Register, LCM_OP_MODE (Offset 0x214) */
|
|
#define LCM_REG_LCM_OP_MODE_16_BIT_MODE_SELECTION() GET_BITS(LCM_REG_OP_MODE, 6, 7)
|
|
#define LCM_REG_LCM_OP_MODE_BIT_SELECTION_BUS_INTERFACE() GET_BITS(LCM_REG_OP_MODE, 4, 5)
|
|
#define LCM_REG_LCM_OP_MODE_BIT_SELECTION_PANEL_INTERFACE() GET_BITS(LCM_REG_OP_MODE, 2, 3)
|
|
#define LCM_REG_LCM_OP_MODE_MCU_SELECTION() GET_BIT(LCM_REG_OP_MODE, 0)
|
|
|
|
/* LCM Enable Register, LCM_ENABLE (Offset 0x228)*/
|
|
#define LCM_REG_LCM_ENABLE_BACKLIGHT_CTRL() GET_BIT(LCM_REG_ENABLE, 12)
|
|
#define LCM_REG_LCM_ENABLE_SIGNAL_INVERSE() GET_BIT(LCM_REG_ENABLE, 11)
|
|
#define LCM_REG_LCM_ENABLE_RESET_ASSERT() GET_BIT(LCM_REG_ENABLE, 8)
|
|
#define LCM_REG_LCM_ENABLE() GET_BIT(LCM_REG_ENABLE, 0)
|
|
|
|
/* LCM Timing Control Register (Offset : 0x200) */
|
|
/* Tpwh width for the read cycles */
|
|
#define LCM_REG_TIMING_SET_Tpwh_r(val) SET_MASKED_BITS(LCM_REG_TIMING, val, 16, 19)
|
|
/* Tas width */
|
|
#define LCM_REG_TIMING_SET_Tas(val) SET_MASKED_BITS(LCM_REG_TIMING, val, 12, 15)
|
|
/* Tah width */
|
|
#define LCM_REG_TIMING_SET_Tah(val) SET_MASKED_BITS(LCM_REG_TIMING, val, 8, 11)
|
|
/* Tpwd width */
|
|
#define LCM_REG_TIMING_SET_Tpwl(val) SET_MASKED_BITS(LCM_REG_TIMING, val, 4, 7)
|
|
/* Tpwh width for write cycles */
|
|
#define LCM_REG_TIMING_SET_Tpwh_w(val) SET_MASKED_BITS(LCM_REG_TIMING, val, 0, 3)
|
|
|
|
/* LCM Ready Register (Offset : 0x204) */
|
|
#define LCM_REG_RDY_READY_FOR_ACCESS BIT0
|
|
#define LCM_REG_RDY_GET_Rdy_C_D GET_BIT(LCM_REG_RDY, 0)
|
|
|
|
/* LCM Data/Command Read Control Register, LCM_RS (Offset 0x208) */
|
|
/* write 1: issue the read data phase at RS=1 */
|
|
#define LCM_REG_RS_DMYRD_RS BIT0
|
|
#define LCM_REG_RS_GET_DMYRD_RS() GET_BIT(LCM_REG_RS, 0)
|
|
#define LCM_REG_RS_SET_DMYRD_RS(val) SET_MASKED_BIT(LCM_REG_RS, val, 0)
|
|
|
|
/* LCM Operation Mode Select Register, LCM_OP_MODE (Offset 0x214) */
|
|
#define LCM_REG_OP_MODE_SET_16bit_mode(val) SET_MASKED_BITS(LCM_REG_TIMING, val, 6, 7)
|
|
#define LCM_REG_OP_MODE_SET_Bus_IF(val) SET_MASKED_BITS(LCM_REG_TIMING, val, 4, 5)
|
|
#define LCM_REG_OP_MODE_SET_Panel_IF(val) SET_MASKED_BITS(LCM_REG_TIMING, val, 2, 3)
|
|
#define LCM_REG_OP_MODE_SET_C68(val) SET_MASKED_BITS(LCM_REG_TIMING, val, 0, 1)
|
|
|
|
/* LCM Enable Register, LCM_ENABLE (Offset 0x228) */
|
|
#define LCM_REG_ENABLE_GET_BLCTRL_SET() GET_BIT(LCM_REG_ENABLE, 12)
|
|
#define LCM_REG_ENABLE_GET_RST_INV() GET_BIT(LCM_REG_ENABLE, 11)
|
|
#define LCM_REG_ENABLE_GET_RST_CLR() GET_BIT(LCM_REG_ENABLE, 9)
|
|
#define LCM_REG_ENABLE_GET_RST_SET() GET_BIT(LCM_REG_ENABLE, 8)
|
|
#define LCM_REG_ENABLE_GET_LCM_En() GET_BIT(LCM_REG_ENABLE, 0)
|
|
|
|
#define LCM_REG_ENABLE_SET_BLCTRL_CLR(val) SET_MASKED_BIT(LCM_REG_ENABLE, val, 13)
|
|
#define LCM_REG_ENABLE_SET_BLCTRL_SET(val) SET_MASKED_BIT(LCM_REG_ENABLE, val, 12)
|
|
#define LCM_REG_ENABLE_SET_RST_INV(val) SET_MASKED_BIT(LCM_REG_ENABLE, val, 11)
|
|
#define LCM_REG_ENABLE_SET_RST_CLR() SET_BIT(LCM_REG_ENABLE, 9)
|
|
//#define LCM_REG_ENABLE_SET_RST_CLR(val) SET_MASKED_BIT(LCM_REG_ENABLE, val, 9)
|
|
//#define LCM_REG_ENABLE_SET_RST_SET() SET_BIT(LCM_REG_ENABLE, val, 8)
|
|
#define LCM_REG_ENABLE_SET_RST_SET(val) //SET_MASKED_BIT(LCM_REG_ENABLE, val, 8)
|
|
#define LCM_REG_ENABLE_SET_LCM_En(val) SET_MASKED_BIT(LCM_REG_ENABLE, val, 0)
|
|
|
|
|
|
|
|
//static u32 _prof_start, _prof_end;
|
|
//static u32 _prof_offset, _prof_total = 0, _prof_frame_cnt = 0;
|
|
#define LCM_PROFILE_ENABLE
|
|
#ifdef LCM_PROFILE_ENABLE
|
|
#define LCM_PROFILE_START() _prof_start = osKernelGetTickCount();
|
|
#define LCM_PROFILE_STOP() { \
|
|
_prof_end = osKernelGetTickCount(); \
|
|
_prof_offset = _prof_end - _prof_start; \
|
|
_prof_total += _prof_offset; \
|
|
++_prof_frame_cnt; \
|
|
/*DSG("[%s] offset=%u average=%u", __func__, _prof_offset, _prof_total / _prof_frame_cnt);*/ \
|
|
}
|
|
#else
|
|
#define LCM_PROFILE_START()
|
|
#define LCM_PROFILE_STOP()
|
|
#endif
|
|
|
|
|
|
#define LCM_OPS_WAIT_TIMEOUT_CNT (1000)
|
|
|
|
enum lcm_signal_cycle {
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X1 = 0x00,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X2 = 0x01,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X3 = 0x02,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X4 = 0x03,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X5 = 0x04,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X6 = 0x05,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X7 = 0x06,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X8 = 0x07,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X9 = 0x08,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X10 = 0x09,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X11 = 0x0A,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X12 = 0x0B,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X13 = 0x0C,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X14 = 0x0D,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X15 = 0x0E,
|
|
LCM_SIGNAL_WIDTH_LC_PCLK_X16 = 0x0F,
|
|
};
|
|
|
|
enum lcm_16bitmode_selection {
|
|
LCM_16BITMODE_ONESHOT = 0x00,
|
|
LCM_16BITMODE_16_AT_MSB = 0x01,
|
|
LCM_16BITMODE_16_AT_LSB = 0x01,
|
|
};
|
|
|
|
enum lcm_data_bus_type {
|
|
LCM_DATA_BUS_8_BITS = 0x00,
|
|
LCM_DATA_BUS_9_BITS = 0x01,
|
|
LCM_DATA_BUS_16_BITS = 0x02,
|
|
LCM_DATA_BUS_18_BITS = 0x03,
|
|
};
|
|
|
|
enum lcm_panel_interface_type {
|
|
LCM_PANEL_INTEFACE_MONO = 0x00,
|
|
LCM_PANEL_INTEFACE_16_BITS = 0x00,
|
|
LCM_PANEL_INTEFACE_18_BITS = 0x00,
|
|
};
|
|
|
|
enum lcm_mcu_interface_mode {
|
|
LCM_MCU_INTERFACE_8080 = 0x00,
|
|
LCM_MCU_INTERFACE_6800 = 0x01,
|
|
};
|
|
|
|
typedef struct {
|
|
uint32_t dp_buffer_addr;
|
|
} kdrv_lcm_context_t;
|
|
kdrv_lcm_context_t kdrv_lcm_ctx;
|
|
static kdrv_lcm_context_t *p_lcm_ctx = &kdrv_lcm_ctx;
|
|
|
|
enum lcm_state {
|
|
LCM_STATE_IDLE = 0,
|
|
LCM_STATE_INITED,
|
|
LCM_STATE_STOPPED,
|
|
LCM_STATE_PROBED,
|
|
LCM_STATE_STARTED,
|
|
};
|
|
|
|
uint8_t _glight = 50;
|
|
|
|
|
|
bool m_show_txt = true;
|
|
|
|
struct mutex display_reg_lock;
|
|
|
|
enum lcm_state m_lcm_state;
|
|
//static osThreadId_t m_tid_lcm;
|
|
|
|
typedef struct {
|
|
int buf_size;
|
|
uint32_t buf_addr;
|
|
bool init_done;
|
|
} kdrv_lcm_fb_t;
|
|
kdrv_lcm_fb_t kdrv_lcm_frame_buffer;
|
|
static kdrv_lcm_fb_t *p_lcm_fb = &kdrv_lcm_frame_buffer;
|
|
|
|
#define PWM6_FREQ_CNT (2000000)
|
|
|
|
kdrv_display_t kdrv_display;
|
|
|
|
/************************************************************************
|
|
* Private API
|
|
************************************************************************/
|
|
static void lcm_wait_ready(uint32_t base)
|
|
{
|
|
unsigned int rdata;
|
|
unsigned int timeout_cnt = 0;
|
|
|
|
while((rdata & LCM_REG_RDY_READY_FOR_ACCESS) != LCM_REG_RDY_READY_FOR_ACCESS)
|
|
{
|
|
rdata = inw(LCM_REG_RDY_P(base));
|
|
timeout_cnt++;
|
|
if (LCM_OPS_WAIT_TIMEOUT_CNT <= timeout_cnt)
|
|
{
|
|
lcm_msg("_lcm_wait_ready timeout : %d\n", timeout_cnt);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void lcm_set_16bitmode_selection(enum lcm_16bitmode_selection sel)
|
|
{
|
|
LCM_REG_OP_MODE_SET_16bit_mode(sel);
|
|
}
|
|
|
|
static void lcm_set_data_bus_type(enum lcm_data_bus_type type)
|
|
{
|
|
LCM_REG_OP_MODE_SET_Bus_IF(type);
|
|
}
|
|
|
|
static void lcm_set_panel_interface_type(enum lcm_panel_interface_type type)
|
|
{
|
|
LCM_REG_OP_MODE_SET_Bus_IF(type);
|
|
}
|
|
|
|
static void lcm_set_mcu_interface_mode(enum lcm_mcu_interface_mode mode)
|
|
{
|
|
LCM_REG_OP_MODE_SET_C68(mode);
|
|
}
|
|
|
|
static void lcm_set_pwh_r(enum lcm_signal_cycle cycle)
|
|
{
|
|
//Tpwh width for the read cycles
|
|
LCM_REG_TIMING_SET_Tpwh_r((u32)cycle);
|
|
}
|
|
|
|
static void lcm_set_as(enum lcm_signal_cycle cycle)
|
|
{
|
|
LCM_REG_TIMING_SET_Tas((u32)cycle);
|
|
}
|
|
|
|
static void lcm_set_ah(enum lcm_signal_cycle cycle)
|
|
{
|
|
LCM_REG_TIMING_SET_Tah((u32)cycle);
|
|
}
|
|
|
|
static void lcm_set_pwl(enum lcm_signal_cycle cycle)
|
|
{
|
|
LCM_REG_TIMING_SET_Tpwl((u32)cycle);
|
|
}
|
|
|
|
static void lcm_set_pwh_w(enum lcm_signal_cycle cycle)
|
|
{
|
|
//Tpwh width for the write cycles
|
|
LCM_REG_TIMING_SET_Tpwh_w((u32)cycle);
|
|
}
|
|
|
|
static void lcm_alloc_framebuffer(void)
|
|
{
|
|
p_lcm_ctx->dp_buffer_addr = KDP_DDR_DRV_LCM_START_ADDR;
|
|
}
|
|
|
|
static __inline int _kdp520_lcm_draw_pixel(
|
|
u32 frame_buffer, int x, int y, u32 width, u16 color)
|
|
{
|
|
*(u16 *)(frame_buffer + ((y * width + x) << 1) + 0) = color;
|
|
return 0;
|
|
}
|
|
|
|
/* reserved functon
|
|
static int kdp520_lcm_reset(struct display_driver_s *display_drv)
|
|
{
|
|
return 0;
|
|
}
|
|
*/
|
|
|
|
|
|
/************************************************************************
|
|
* Public API
|
|
************************************************************************/
|
|
kdrv_display_t *kdrv_display_initialize(void)
|
|
{
|
|
kdrv_display.base = SLCD_FTLCDC210_PA_BASE;
|
|
|
|
SCU_EXTREG_SWRST_MASK1_SET_lcm_reset_n(1);
|
|
SCU_EXTREG_MISC_SET_lcm_cken(1);
|
|
|
|
lcm_set_as(LCM_SIGNAL_WIDTH_LC_PCLK_X2);
|
|
lcm_set_ah(LCM_SIGNAL_WIDTH_LC_PCLK_X2);
|
|
lcm_set_pwl(LCM_SIGNAL_WIDTH_LC_PCLK_X2);
|
|
lcm_set_pwh_r(LCM_SIGNAL_WIDTH_LC_PCLK_X4);
|
|
lcm_set_pwh_w(LCM_SIGNAL_WIDTH_LC_PCLK_X4);
|
|
|
|
lcm_set_16bitmode_selection(LCM_16BITMODE_ONESHOT);
|
|
lcm_set_data_bus_type(LCM_DATA_BUS_16_BITS);
|
|
//lcm_set_data_bus_type(LCM_DATA_BUS_8_BITS);
|
|
|
|
lcm_set_panel_interface_type(LCM_PANEL_INTEFACE_18_BITS);
|
|
lcm_set_mcu_interface_mode(LCM_MCU_INTERFACE_8080);
|
|
|
|
// reset lcm
|
|
{
|
|
LCM_REG_ENABLE_SET_RST_SET(); // power on reset
|
|
kdrv_delay_us(5000);
|
|
//delay_ms(50);
|
|
LCM_REG_ENABLE_SET_RST_CLR();
|
|
LCM_REG_ENABLE_SET_LCM_En(1);
|
|
LCM_REG_ENABLE_SET_BLCTRL_SET(1);
|
|
}
|
|
//change to probed
|
|
m_lcm_state = LCM_STATE_INITED;
|
|
return &kdrv_display;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_set_pen(kdrv_display_t *display_drv, uint16_t color, unsigned int width)
|
|
{
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
display_drv->pen_info.color = color;
|
|
display_drv->pen_info.width = width;
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_set_params(kdrv_display_t *display_drv, struct video_input_params *params)
|
|
{
|
|
struct video_input_params *p;
|
|
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
p = &display_drv->vi_params;
|
|
memcpy(p, params, sizeof(*params));
|
|
lcm_msg(" *params=%u i=%u", sizeof(*params), params->input_xres);
|
|
|
|
display_drv->fb_size = calc_framesize(p->input_xres, p->input_yres, p->input_fmt);
|
|
|
|
lcm_msg("[%s] video_input_params->input_xres=%u", __func__, p->input_xres);
|
|
lcm_msg("[%s] video_input_params->input_yres=%u", __func__, p->input_yres);
|
|
lcm_msg("[%s] video_input_params->input_fmt=%x", __func__, p->input_fmt);
|
|
lcm_msg("[%s] display_driver->fb_size=%d", __func__, display_drv->fb_size);
|
|
kdrv_display_set_backlight(display_drv, 100);
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_get_params(kdrv_display_t *display_drv, struct video_input_params *params)
|
|
{
|
|
struct video_input_params *p;
|
|
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
p = &display_drv->vi_params;
|
|
//memcpy(p, params, sizeof(*params));
|
|
memcpy(params, p, sizeof(*params));
|
|
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_set_camera(kdrv_display_t *display_drv, uint8_t cam_idx)
|
|
{
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
display_drv->cam_src_idx = cam_idx;
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_buffer_initialize(struct video_input_params *params)
|
|
{
|
|
p_lcm_fb->buf_size = calc_framesize(params->input_xres, params->input_yres, params->input_fmt);
|
|
p_lcm_fb->buf_addr = kmdw_ddr_reserve(p_lcm_fb->buf_size);
|
|
p_lcm_fb->init_done = true;
|
|
lcm_alloc_framebuffer();
|
|
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
uint32_t kdrv_display_get_buffer(void)
|
|
{
|
|
return p_lcm_fb->buf_addr;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_start(kdrv_display_t *display_drv)
|
|
{
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
kdrv_lcm_write_cmd(display_drv->base, 0x29);
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_stop(kdrv_display_t *display_drv)
|
|
{
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
kdrv_display_set_backlight(display_drv, 0);
|
|
kdrv_lcm_write_cmd(display_drv->base, 0x28);
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_draw_line(kdrv_display_t *display_drv,
|
|
uint32_t xs, uint32_t ys, uint32_t xe, uint32_t ye)
|
|
{
|
|
uint32_t x_pos, y_pos;
|
|
uint32_t x_unit = 1;
|
|
uint32_t y_unit = 1;
|
|
uint32_t frame_width;
|
|
uint32_t frame_height;
|
|
uint32_t _addr = p_lcm_ctx->dp_buffer_addr;
|
|
uint16_t color;
|
|
uint16_t pen_width;
|
|
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
frame_width = display_drv->vi_params.input_xres;
|
|
frame_height = display_drv->vi_params.input_yres;
|
|
color = display_drv->pen_info.color;
|
|
pen_width = display_drv->pen_info.width;
|
|
if(xs == xe)
|
|
{
|
|
if(ys > ye)
|
|
{
|
|
ys ^= ye;
|
|
ye ^= ys;
|
|
ys ^= ye;
|
|
}
|
|
|
|
for(y_pos = ys; y_pos <= ye; y_pos += y_unit)
|
|
{
|
|
for(x_pos = xs; (x_pos < xs+pen_width) && (x_pos < frame_width); x_pos += x_unit)
|
|
{
|
|
_kdp520_lcm_draw_pixel(_addr, x_pos, y_pos, frame_width, color);
|
|
}
|
|
}
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
else if(ys == ye)
|
|
{
|
|
if(xs > xe)
|
|
{
|
|
xs ^= xe;
|
|
xe ^= xs;
|
|
xs ^= xe;
|
|
}
|
|
|
|
for(x_pos = xs; x_pos <= xe; x_pos += x_unit)
|
|
{
|
|
for(y_pos = ys; (y_pos < ys+pen_width) && (y_pos < frame_height); y_pos += y_unit)
|
|
{
|
|
_kdp520_lcm_draw_pixel(_addr, x_pos, y_pos, frame_width, color);
|
|
}
|
|
}
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
return KDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_draw_rect(kdrv_display_t *display_drv, uint32_t org_x, uint32_t org_y, uint32_t width, uint32_t height)
|
|
{
|
|
uint16_t color;
|
|
uint32_t frame_width;
|
|
uint32_t frame_height;
|
|
uint32_t border_size;
|
|
uint32_t _addr = p_lcm_ctx->dp_buffer_addr;
|
|
int x_pos, y_pos;
|
|
int x_unit = 1;
|
|
int y_unit = 1;
|
|
int top = org_y;
|
|
int left = org_x;
|
|
int right;
|
|
int bottom;
|
|
int left_border;
|
|
int right_border;
|
|
int top_lower;
|
|
int bottom_upper;
|
|
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
color = display_drv->pen_info.color;
|
|
frame_width = display_drv->vi_params.input_xres;
|
|
frame_height = display_drv->vi_params.input_yres;
|
|
border_size = display_drv->pen_info.width;
|
|
left_border = left + border_size;
|
|
right_border = right - border_size;
|
|
top_lower = top + border_size;
|
|
bottom_upper = bottom - border_size;
|
|
|
|
for (y_pos=(top>=0)?top:0; (y_pos < bottom) && (y_pos >= 0) && (y_pos < frame_height); y_pos += y_unit)
|
|
{
|
|
if ((y_pos >= top && y_pos < top_lower) || (y_pos >= bottom_upper))
|
|
{
|
|
for (x_pos=(left>=0)?left:0; (x_pos < right) && (x_pos < frame_width); x_pos += x_unit)
|
|
{
|
|
//DSG("x_pos=%d y_pos=%d", x_pos, y_pos);
|
|
_kdp520_lcm_draw_pixel(_addr, x_pos, y_pos, frame_width, color);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (x_pos=(left>=0)?left:0; (x_pos < left_border) && (x_pos < frame_width); x_pos += x_unit)
|
|
{
|
|
//DSG("x_pos=%d y_pos=%d", x_pos, y_pos);
|
|
_kdp520_lcm_draw_pixel(_addr, x_pos, y_pos, frame_width, color);
|
|
}
|
|
|
|
for (x_pos=(right_border>=0)?right_border:0; (x_pos < right) && (x_pos < frame_width); x_pos += x_unit)
|
|
{
|
|
//DSG("x_pos=%d y_pos=%d", x_pos, y_pos);
|
|
_kdp520_lcm_draw_pixel(_addr, x_pos, y_pos, frame_width, color);
|
|
}
|
|
}
|
|
}
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_draw_static_rect(kdrv_display_t *display_drv, uint32_t org_x, uint32_t org_y, uint32_t width, uint32_t height)
|
|
{
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_test_pattern_gen(kdrv_display_t *display_drv, bool pat_gen)
|
|
{
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_fill_rect(kdrv_display_t *display_drv,
|
|
uint32_t org_x, uint32_t org_y, uint32_t width, uint32_t height)
|
|
{
|
|
uint32_t x_pos, y_pos;
|
|
uint32_t _addr = p_lcm_ctx->dp_buffer_addr;
|
|
uint32_t frame_width;
|
|
uint32_t frame_height;
|
|
uint16_t color;
|
|
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
frame_width = display_drv->vi_params.input_xres;
|
|
frame_height = display_drv->vi_params.input_yres;
|
|
color = display_drv->pen_info.color;
|
|
if((org_x >= frame_width)
|
|
|| (org_y >= frame_height)
|
|
|| ((org_x + width) > frame_width)
|
|
|| ((org_y + height) > frame_height))
|
|
{
|
|
return KDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
for(y_pos=org_y; y_pos<(org_y+height); y_pos++)
|
|
{
|
|
for(x_pos=org_x; x_pos<(org_x+width); x_pos++)
|
|
{
|
|
_kdp520_lcm_draw_pixel(_addr, x_pos, y_pos, frame_width, color);
|
|
}
|
|
}
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_draw_bitmap(kdrv_display_t *display_drv,
|
|
uint32_t org_x, uint32_t org_y, uint32_t width, uint32_t height, void* pBuf)
|
|
{
|
|
uint32_t* buf = pBuf;
|
|
uint32_t y_pos;
|
|
uint32_t _addr = p_lcm_ctx->dp_buffer_addr;
|
|
uint32_t frame_width;
|
|
uint32_t frame_height;
|
|
uint8_t bpp = 2;
|
|
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
frame_width = display_drv->vi_params.input_xres;
|
|
frame_height = display_drv->vi_params.input_yres;
|
|
|
|
if((org_x >= frame_width)
|
|
|| (org_y >= frame_height)
|
|
|| ((org_x + width) > frame_width)
|
|
|| ((org_y + height) > frame_height))
|
|
{
|
|
return KDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
for(y_pos=org_y; y_pos<(org_y+height); y_pos++)
|
|
{
|
|
memcpy((void *)(_addr+((y_pos*frame_width+org_x)<<1)), (void *)buf, width*bpp);
|
|
buf += width*bpp;
|
|
}
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_set_backlight(kdrv_display_t *display_drv, int light)
|
|
{
|
|
uint32_t duty;
|
|
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
duty = (PWM6_FREQ_CNT * light) / 100;
|
|
kdrv_pwm_config(PWMTIMER6, PWM_POLARITY_INVERSED, duty, PWM6_FREQ_CNT, 0);
|
|
kdrv_pwm_enable(PWMTIMER6);
|
|
|
|
if(light == 0)
|
|
return KDRV_STATUS_OK;
|
|
|
|
_glight = light;
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_set_frame_margin_len(uint16_t margin_len)
|
|
{
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
uint16_t kdrv_display_get_frame_margin_len(void)
|
|
{
|
|
return 0;;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_set_review_snapshot_en(bool enable)
|
|
{
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
bool kdrv_display_get_review_snapshot_en(void)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
kdrv_status_t kdrv_display_set_snapshot_preview_en(bool enable)
|
|
{
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
bool kdrv_display_get_snapshot_preview_en(void)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
kdrv_status_t kdrv_lcm_write_cmd(uint32_t base, unsigned char data)
|
|
{
|
|
mutex_lock(&display_reg_lock);
|
|
|
|
lcm_wait_ready(base);
|
|
outb(LCM_REG_CMD_P(base), data);
|
|
|
|
mutex_unlock(&display_reg_lock);
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_lcm_write_data(uint32_t base, unsigned char data)
|
|
{
|
|
mutex_lock(&display_reg_lock);
|
|
|
|
lcm_wait_ready(base);
|
|
outb(LCM_REG_DATA_P(base), data);
|
|
|
|
mutex_unlock(&display_reg_lock);
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
unsigned int kdrv_lcm_read_data(uint32_t base)
|
|
{
|
|
mutex_lock(&display_reg_lock);
|
|
|
|
lcm_wait_ready(base);
|
|
outb(LCM_REG_RS_P(base), LCM_REG_RS_DMYRD_RS);
|
|
|
|
lcm_wait_ready(base);
|
|
|
|
mutex_unlock(&display_reg_lock);
|
|
|
|
return inw(LCM_REG_DATA_P(base));
|
|
}
|
|
|
|
kdrv_status_t kdrv_lcm_pressingnir(kdrv_display_t *display_drv, u32 addr)
|
|
{
|
|
uint32_t row_idx = 0;
|
|
uint32_t col_idx = 0;
|
|
uint32_t index = 0;
|
|
uint32_t readAddr;
|
|
uint32_t writeAddr = KDP_DDR_DRV_LCM_START_ADDR;
|
|
uint32_t totalpoint;
|
|
uint16_t data_buf;
|
|
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
addr = addr + 100 + 480*NIR_Y_OFFSET;
|
|
readAddr = addr;
|
|
|
|
totalpoint = (320*240);
|
|
|
|
for(index = 0; index < totalpoint; index++)
|
|
{
|
|
data_buf = (u16)inb(readAddr);
|
|
data_buf = (u16)((data_buf>>3)<<11) | ((data_buf>>2)<<5) | ((data_buf>>3)<<0);
|
|
|
|
outw(writeAddr,data_buf);
|
|
writeAddr = writeAddr + 2;
|
|
|
|
if (0 == index%240 )
|
|
{
|
|
col_idx = 0;
|
|
row_idx = row_idx + 1;
|
|
readAddr = addr + 480*row_idx;
|
|
}
|
|
else
|
|
{
|
|
col_idx = col_idx + 1;
|
|
readAddr = readAddr + 1;
|
|
}
|
|
}
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
kdrv_status_t kdrv_lcm_pressing(kdrv_display_t *display_drv, u32 addr)
|
|
{
|
|
const uint16_t input_xres = display_drv->vi_params.input_xres;
|
|
const uint16_t input_yres = display_drv->vi_params.input_yres;
|
|
|
|
uint32_t index = 0;
|
|
uint32_t readAddr = addr;
|
|
uint32_t writeAddr = KDP_DDR_DRV_LCM_START_ADDR;
|
|
uint16_t lcm_w = input_xres;
|
|
uint16_t lcm_h = input_yres;
|
|
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
readAddr += LCD_DISPLAY_X_OFFSET * 2 + LCD_DISPLAY_Y_OFFSET * 640 *2;
|
|
for(index =0;index < lcm_h;index++)
|
|
{
|
|
kdrv_gdma_memcpy((uint32_t)(writeAddr), (uint32_t)(readAddr), lcm_w*2);
|
|
readAddr += 640*2;
|
|
writeAddr += lcm_w*2;
|
|
}
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
extern osMutexId_t mutex_snapshot;
|
|
kdrv_status_t kdrv_display_update_draw_fb(kdrv_display_t *display_drv, uint32_t addr, uint8_t cam_idx)
|
|
{
|
|
if(display_drv == NULL)
|
|
return KDRV_STATUS_ERROR;
|
|
|
|
display_drv->cam_src_idx = cam_idx;
|
|
|
|
if(cam_idx == MIPI_CAM_RGB){
|
|
#if CFG_SNAPSHOT_ENABLE == YES
|
|
osMutexAcquire(mutex_snapshot, 1000);
|
|
kdrv_lcm_pressing(display_drv, addr);
|
|
osMutexRelease(mutex_snapshot);
|
|
#else
|
|
kdrv_lcm_pressing(display_drv, addr);
|
|
#endif
|
|
}
|
|
else{
|
|
#if CFG_SNAPSHOT_ENABLE == YES
|
|
osMutexAcquire(mutex_snapshot, 1000);
|
|
kdrv_lcm_pressingnir(display_drv, addr);//pressing to display addr
|
|
osMutexRelease(mutex_snapshot);
|
|
#else
|
|
kdrv_lcm_pressingnir(display_drv, addr);//pressing to display addr
|
|
#endif
|
|
}
|
|
return KDRV_STATUS_OK;
|
|
}
|
|
|
|
uint8_t kdrv_lcm_get_backlight(void)
|
|
{
|
|
return _glight;
|
|
}
|
|
|
|
uint32_t kdrv_lcm_get_db_frame(void)
|
|
{
|
|
return p_lcm_ctx->dp_buffer_addr;
|
|
}
|