1640 lines
51 KiB
C
1640 lines
51 KiB
C
/**
|
|
* @file sdrv_dc_drv.c
|
|
* @brief sdrv dc driver source.
|
|
*
|
|
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <board.h>
|
|
#include <debug.h>
|
|
#include <dispss/dc_reg.h>
|
|
#include <dispss/disp.h>
|
|
#include <dispss/disp_data_type.h>
|
|
#include <dispss/disp_reg_rw.h>
|
|
#include <dispss/dispss_log.h>
|
|
#include <dispss/warning_image.h>
|
|
#include <udelay/udelay.h>
|
|
|
|
#define DC_NO_UPDATE 0x0000
|
|
#define DC_GP_UPDATE 0x0001
|
|
#define DC_SP_UPDATE 0x0002
|
|
#define DC_DP0_UPDATE 0x0004
|
|
#define DC_DP1_UPDATE 0x0004
|
|
#define DC_TCON_UPDATE 0x0008
|
|
#define DC_MLC_UPDATE 0x0010
|
|
#define DC_GAMMA_UPDATE 0x0020
|
|
#define DC_DITHER_UPDATE 0x0040
|
|
#define DC_CSC_UPDATE 0x0080
|
|
#define DC_CRC_UPDATE 0x0800
|
|
|
|
#define POLYNOMIAL 0x04c11db7L
|
|
static unsigned int crc_table[256] = {0};
|
|
|
|
static const unsigned int csc_param[5][15] = {
|
|
{/*bt601 YCbCr to RGB(0-255)*/
|
|
0x094F, 0x0000, 0x0CC4, 0x094F, 0x3CE0, 0x397F, 0x094F, 0x1024, 0x0000,
|
|
0x0000, 0x0000, 0x0000, 0x0040, 0x0200, 0x0200},
|
|
{/*basic YUV to RGB*/
|
|
0x0800, 0x0000, 0x091E, 0x0800, 0x7CD8, 0x7B5B, 0x0800, 0x1041, 0x0000,
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
|
|
|
|
{/*bt709 YCbCr to RGB(16-235)*/
|
|
0x0800, 0x0000, 0x0C51, 0x0800, 0x3E8A, 0x3C54, 0x0800, 0x0E87, 0x0000,
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0200},
|
|
{/*RGB to YCbCr*/
|
|
0x0000},
|
|
{/*RGB to YUV*/
|
|
0x0000}};
|
|
|
|
static unsigned int dc_triggle_type = DC_NO_UPDATE;
|
|
struct tcon_timing t_timing;
|
|
|
|
static unsigned int get_l_addr(unsigned long addr)
|
|
{
|
|
unsigned int addr_l;
|
|
|
|
addr_l = (unsigned int)(addr & 0x00000000FFFFFFFF);
|
|
return addr_l;
|
|
}
|
|
|
|
static unsigned int get_h_addr(unsigned long addr)
|
|
{
|
|
unsigned int addr_h;
|
|
|
|
addr_h = (unsigned int)(addr & 0xFFFFFFFF00000000);
|
|
return addr_h;
|
|
}
|
|
|
|
unsigned int get_csi_dc_ratio_num(int ratio)
|
|
{
|
|
unsigned int ret = 0;
|
|
switch (ratio) {
|
|
case CSI_DC_1_1:
|
|
ret = 1;
|
|
break;
|
|
case CSI_DC_1_2:
|
|
ret = 2;
|
|
break;
|
|
case CSI_DC_1_3:
|
|
ret = 3;
|
|
break;
|
|
case CSI_DC_1_4:
|
|
ret = 4;
|
|
break;
|
|
default:
|
|
DISPSS_LOG_INFO("csi_dc ratio param err");
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void timing_to_tcon_timing(struct display_timing *timing,
|
|
struct tcon_timing *t_timing)
|
|
{
|
|
DISPSS_LOG_INFO("LCD Timing:");
|
|
DISPSS_LOG_INFO("hact: %d, hsync: %d, hfp: %d, hbp: %d", timing->hactive,
|
|
timing->hsync_len, timing->hfront_porch,
|
|
timing->hback_porch);
|
|
DISPSS_LOG_INFO("vact: %d, vsync: %d, vfp: %d, vbp: %d", timing->vactive,
|
|
timing->vsync_len, timing->vfront_porch,
|
|
timing->vback_porch);
|
|
|
|
t_timing->hact = timing->hactive;
|
|
t_timing->hsync = timing->hsync_len;
|
|
t_timing->hsbp = timing->hsync_len + timing->hback_porch;
|
|
t_timing->htol = timing->hactive + timing->hfront_porch +
|
|
timing->hsync_len + timing->hback_porch;
|
|
|
|
t_timing->vact = timing->vactive;
|
|
t_timing->vsync = timing->vsync_len;
|
|
t_timing->vsbp = timing->vsync_len + timing->vback_porch;
|
|
t_timing->vtol = timing->vactive + timing->vfront_porch +
|
|
timing->vsync_len + timing->vback_porch;
|
|
|
|
DISPSS_LOG_INFO("Tcon Timing:");
|
|
DISPSS_LOG_INFO("hact: %d, hsync: %d, hsbp: %d, htol: %d", t_timing->hact,
|
|
t_timing->hsync, t_timing->hsbp, t_timing->htol);
|
|
DISPSS_LOG_INFO("vact: %d, vsync: %d, vsbp: %d, vtol: %d", t_timing->vact,
|
|
t_timing->vsync, t_timing->vsbp, t_timing->vtol);
|
|
}
|
|
|
|
static void dc_sp_sdw_triggle(struct dc_dev *dev)
|
|
{
|
|
unsigned long base = dev->base;
|
|
|
|
disp_write(base, DC_RDF00(0), 1);
|
|
}
|
|
|
|
static void dc_gp_sdw_triggle(struct dc_dev *dev)
|
|
{
|
|
unsigned long base = dev->base;
|
|
|
|
disp_write(base, DC_RCF00, 1);
|
|
}
|
|
|
|
static void dc_force_update(struct dc_dev *dev)
|
|
{
|
|
static bool first_triggle = false;
|
|
unsigned long base = dev->base;
|
|
|
|
if (!first_triggle) {
|
|
first_triggle = true;
|
|
disp_write(base, DC_RA008, 1);
|
|
}
|
|
}
|
|
static void dc_triggle(struct dc_dev *dev)
|
|
{
|
|
unsigned val = 0;
|
|
unsigned long base = dev->base;
|
|
|
|
if (dc_triggle_type & DC_SP_UPDATE)
|
|
dc_sp_sdw_triggle(dev);
|
|
|
|
if (dc_triggle_type & DC_GP_UPDATE)
|
|
dc_gp_sdw_triggle(dev);
|
|
|
|
if (dc_triggle_type &
|
|
(DC_MLC_UPDATE | DC_CSC_UPDATE | DC_GAMMA_UPDATE | DC_DITHER_UPDATE))
|
|
val = reg_value(1, val, DC_SHIFT01_RA004, DC_MASK01_RA004);
|
|
|
|
if (dc_triggle_type & DC_CRC_UPDATE)
|
|
val = reg_value(1, val, DC_SHIFT03_RA004, DC_MASK03_RA004);
|
|
|
|
if (dc_triggle_type & DC_TCON_UPDATE)
|
|
val = reg_value(1, val, DC_SHIFT02_RA004, DC_MASK02_RA004);
|
|
|
|
disp_write(base, DC_RA004, val);
|
|
|
|
val = reg_value(1, val, DC_SHIFT00_RA004, DC_MASK00_RA004);
|
|
disp_write(base, DC_RA004, val);
|
|
|
|
dc_triggle_type = DC_NO_UPDATE;
|
|
|
|
dc_force_update(dev);
|
|
}
|
|
|
|
static unsigned int dc_check_triggle_status(struct dc_dev *dev)
|
|
{
|
|
unsigned int val = 0;
|
|
unsigned long base = dev->base;
|
|
|
|
val = disp_read(base, DC_RA004);
|
|
return val & 0x1;
|
|
}
|
|
|
|
static void dc_ms_mode(struct dc_dev *dev)
|
|
{
|
|
unsigned long base = dev->base;
|
|
unsigned int val = 0;
|
|
|
|
val = disp_read(base, DC_RA000);
|
|
val = reg_value(0, val, DC_SHIFT01_RA000, DC_MASK01_RA000);
|
|
disp_write(base, DC_RA000, val);
|
|
}
|
|
|
|
static void dc_irq_disable(struct dc_dev *dev)
|
|
{
|
|
unsigned long base = dev->base;
|
|
|
|
disp_write(base, DC_RA020, DC_INIT_DEF_MASK);
|
|
disp_write(base, DC_RA120, DC_INIT_DEF_MASK);
|
|
|
|
disp_write(base, DC_RJ008, 0);
|
|
}
|
|
|
|
static void dc_irq_init(struct dc_dev *dev)
|
|
{
|
|
unsigned long base = dev->base;
|
|
unsigned int val = 0;
|
|
|
|
/*enable crc32 error irq*/
|
|
val = 0xFF << DC_SHIFT08_RJ004;
|
|
disp_write(base, DC_RJ008, val);
|
|
}
|
|
|
|
static void dc_rdma_init(struct dc_dev *dev)
|
|
{
|
|
const unsigned short wml_cfg[] = {0x40, 0x10, 0x10, 0x20};
|
|
const unsigned short d_depth_cfg[] = {8, 2, 2, 4};
|
|
const unsigned short c_depth_cfg[] = {4, 1, 1, 2};
|
|
const unsigned char sche_cfg[] = {0x04, 0x01, 0x01, 0x04};
|
|
const unsigned char p1_cfg[] = {0x30, 0x20, 0x20, 0x30};
|
|
const unsigned char p0_cfg[] = {0x10, 0x08, 0x08, 0x10};
|
|
const unsigned char burst_mode_cfg[] = {0x00, 0x00, 0x00, 0x00};
|
|
const unsigned char burst_len_cfg[] = {0x04, 0x04, 0x04, 0x04};
|
|
const unsigned char wml_req_inv[] = {0xa0, 0xa0, 0xa0, 0xa0};
|
|
const unsigned char wml_down[] = {1, 1, 1, 1};
|
|
const unsigned char wml_up[] = {6, 6, 6, 6};
|
|
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
for (int i = 0; i < RDMA_CHN_COUNT; i++) {
|
|
disp_write(base, DC_RB000(i), wml_cfg[i]);
|
|
}
|
|
|
|
disp_write(base, DC_RB400(0), wml_cfg[3]);
|
|
|
|
for (int i = 0; i < RDMA_CHN_COUNT; i++) {
|
|
disp_write(base, DC_RB004(i), d_depth_cfg[i]);
|
|
}
|
|
|
|
disp_write(base, DC_RB404(0), d_depth_cfg[3]);
|
|
|
|
for (int i = 0; i < RDMA_CHN_COUNT; i++) {
|
|
disp_write(base, DC_RB008(i), c_depth_cfg[i]);
|
|
}
|
|
|
|
disp_write(base, DC_RB408(0), c_depth_cfg[3]);
|
|
|
|
for (int i = 0; i < RDMA_CHN_COUNT; i++) {
|
|
val = reg_value(sche_cfg[i], 0, DC_SHIFT16_RB00C,
|
|
DC_MASK16_RB00C);
|
|
val = reg_value(p1_cfg[i], val, DC_SHIFT08_RB00C,
|
|
DC_MASK08_RB00C);
|
|
val = reg_value(p0_cfg[i], val, DC_SHIFT00_RB00C,
|
|
DC_MASK00_RB00C);
|
|
disp_write(base, DC_RB00C(i), val);
|
|
disp_write(base, DC_RB40C(i), val);
|
|
}
|
|
|
|
for (int i = 0; i < RDMA_CHN_COUNT; i++) {
|
|
val = reg_value(burst_mode_cfg[i], 0, DC_SHIFT03_RB010,
|
|
DC_MASK03_RB010);
|
|
val = reg_value(burst_len_cfg[i], val, DC_SHIFT00_RB010,
|
|
DC_MASK00_RB010);
|
|
disp_write(base, DC_RB010(i), val);
|
|
disp_write(base, DC_RB410(i), val);
|
|
}
|
|
|
|
for (int i = 0; i < RDMA_CHN_COUNT; i++) {
|
|
val = reg_value(wml_req_inv[i], 0, DC_SHIFT16_RB01C,
|
|
DC_MASK16_RB01C);
|
|
val = reg_value(wml_down[i], val, DC_SHIFT04_RB01C,
|
|
DC_MASK04_RB01C);
|
|
val = reg_value(wml_up[i], val, DC_SHIFT00_RB01C,
|
|
DC_MASK00_RB01C);
|
|
disp_write(base, DC_RB01C(i), val);
|
|
disp_write(base, DC_RB41C(i), val);
|
|
}
|
|
|
|
disp_write(base, DC_RB220, RDMA_INT_DEF_MASK);
|
|
disp_write(base, DC_RB620, RDMA_INT_DEF_MASK);
|
|
|
|
val = reg_value(1, 0, DC_SHIFT01_RB100, DC_MASK01_RB100);
|
|
val = reg_value(1, val, DC_SHIFT00_RB100, DC_MASK00_RB100);
|
|
disp_write(base, DC_RB100, val);
|
|
disp_write(base, DC_RB500, val);
|
|
}
|
|
|
|
/*NOTE: Timing regs value = real vaule minus 1*/
|
|
static void dc_set_tcon_timing(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
unsigned int kick_x, kick_y;
|
|
|
|
timing_to_tcon_timing(dev->panel->timing, &t_timing);
|
|
|
|
/* Horizontal active size && total horizontal size in pixels */
|
|
val = reg_value(t_timing.hact - 1, 0, DC_SHIFT16_RG000, DC_MASK16_RG000);
|
|
val = reg_value(t_timing.htol - 1, val, DC_SHIFT00_RG000, DC_MASK00_RG000);
|
|
disp_write(base, DC_RG000, val);
|
|
|
|
/*Horizontal back porch size && wdith of hsync pulse in pixels.*/
|
|
val = reg_value(t_timing.hsbp - 1, 0, DC_SHIFT16_RG004, DC_MASK16_RG004);
|
|
val = reg_value(t_timing.hsync - 1, val, DC_SHIFT00_RG004, DC_MASK00_RG004);
|
|
disp_write(base, DC_RG004, val);
|
|
|
|
/*Vertical active size && total vertical size in lines.*/
|
|
val = reg_value(t_timing.vact - 1, 0, DC_SHIFT16_RG008, DC_MASK16_RG008);
|
|
val = reg_value(t_timing.vtol - 1, val, DC_SHIFT00_RG008, DC_MASK00_RG008);
|
|
disp_write(base, DC_RG008, val);
|
|
|
|
/*Vertical back porch size && width of vsync pulse in lines.*/
|
|
val = reg_value(t_timing.vsbp - 1, 0, DC_SHIFT16_RG00C, DC_MASK16_RG00C);
|
|
val = reg_value(t_timing.vsync - 1, val, DC_SHIFT00_RG00C, DC_MASK00_RG00C);
|
|
disp_write(base, DC_RG00C, val);
|
|
|
|
/*TCON TRCL*/
|
|
val = reg_value(0, 0, DC_SHIFT06_RG010, DC_MASK06_RG010);
|
|
val = reg_value(1, val, DC_SHIFT05_RG010, DC_MASK05_RG010);
|
|
val = reg_value(dev->panel->timing->dsp_clk_pol, val,
|
|
DC_SHIFT04_RG010, DC_MASK04_RG010);
|
|
val = reg_value(dev->panel->timing->de_pol, val, DC_SHIFT03_RG010,
|
|
DC_MASK03_RG010);
|
|
val = reg_value(dev->panel->timing->vsync_pol, val, DC_SHIFT02_RG010,
|
|
DC_MASK02_RG010);
|
|
val = reg_value(dev->panel->timing->hsync_pol, val, DC_SHIFT01_RG010,
|
|
DC_MASK01_RG010);
|
|
disp_write(base, DC_RG010, val);
|
|
|
|
for (int i = 0; i < KICK_LAYER_COUNT; i++) {
|
|
kick_y = t_timing.vact + 1;
|
|
kick_x = 20 + i * 20;
|
|
|
|
if (kick_x > t_timing.htol - 1)
|
|
kick_x = t_timing.htol - 1;
|
|
|
|
val = reg_value(kick_y, 0, DC_SHIFT16_RG020,
|
|
DC_MASK16_RG020);
|
|
val = reg_value(kick_x, val, DC_SHIFT00_RG020,
|
|
DC_MASK00_RG020);
|
|
disp_write(base, DC_RG020(i), val);
|
|
|
|
if (i != 4)
|
|
disp_write(base, DC_RG024(i), 1);
|
|
else
|
|
disp_write(base, DC_RG024(i), 0);
|
|
}
|
|
|
|
dc_triggle_type |= DC_TCON_UPDATE;
|
|
}
|
|
|
|
static void dc_tcon_init(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
dc_set_tcon_timing(dev);
|
|
|
|
/*TCON Trigger*/
|
|
val = disp_read(base, DC_RA004);
|
|
val = reg_value(1, val, DC_SHIFT02_RA004, DC_MASK02_RA004);
|
|
disp_write(base, DC_RA004, val);
|
|
}
|
|
|
|
static void dc_mlc_init(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
const unsigned char prot_val[] = {0x07, 0x07, 0x07, 0x07};
|
|
const unsigned char alpha_bld[] = {0xF, 0xF, 0xF, 0xF, 0xF};
|
|
const unsigned char layer_out[] = {0xF, 0xF, 0xF, 0xF, 0xF};
|
|
|
|
for (int i = 0; i < MLC_LAYER_COUNT; i++) {
|
|
val = reg_value(prot_val[i], 0, DC_SHIFT08_RE000,
|
|
DC_MASK08_RE000);
|
|
val =
|
|
reg_value(1, val, DC_SHIFT02_RE000, DC_MASK02_RE000);
|
|
disp_write(base, DC_RE000(i), val);
|
|
disp_write(base, DC_RF000(i), val);
|
|
|
|
disp_write(base, DC_RE018(i), 0xFF);
|
|
disp_write(base, DC_RF018(i), 0xFF);
|
|
}
|
|
|
|
for (int i = 0; i < MLC_PATH_COUNT; i++) {
|
|
val =
|
|
reg_value(alpha_bld[i], 0, DC_SHIFT16_RE200, DC_MASK16_RE200);
|
|
val = reg_value(layer_out[i], val, DC_SHIFT00_RE200,
|
|
DC_MASK00_RE200);
|
|
disp_write(base, DC_RE200(i), val);
|
|
disp_write(base, DC_RF200(i), val);
|
|
}
|
|
|
|
disp_write(base, DC_RE230, 0x0);
|
|
disp_write(base, DC_RE234, 0xFFFF);
|
|
disp_write(base, DC_RF234, 0xFFFF);
|
|
}
|
|
|
|
static void dc_spipe_init(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
for (int i = 0; i < SP_COUNT; i++) {
|
|
val = disp_read(base, DC_RD200(i));
|
|
val = reg_value(1, val, DC_SHIFT16_RD200, DC_MASK16_RD200);
|
|
disp_write(base, DC_RD200(i), val);
|
|
|
|
val = disp_read(base, DC_RD204(i));
|
|
val = reg_value(1, val, DC_SHIFT16_RD204, DC_MASK16_RD204);
|
|
disp_write(base, DC_RD204(i), val);
|
|
|
|
val = disp_read(base, DC_RD208(i));
|
|
val = reg_value(1, val, DC_SHIFT16_RD208, DC_MASK16_RD208);
|
|
disp_write(base, DC_RD208(i), val);
|
|
|
|
val = disp_read(base, DC_RD20C(i));
|
|
val = reg_value(1, val, DC_SHIFT16_RD20C, DC_MASK16_RD20C);
|
|
disp_write(base, DC_RD20C(i), val);
|
|
}
|
|
}
|
|
|
|
static void dc_gpipe_init(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = reg_value(1, 0, DC_SHIFT00_RC044, DC_MASK00_RC044);
|
|
disp_write(base, DC_RC044, val);
|
|
|
|
val = reg_value(1, 0, DC_SHIFT00_RC200, DC_MASK00_RC200);
|
|
disp_write(base, DC_RC200, val);
|
|
|
|
val = reg_value(csc_param[0][1], 0, DC_SHIFT16_RC204,
|
|
DC_MASK16_RC204);
|
|
val = reg_value(csc_param[0][0], val, DC_SHIFT00_RC204,
|
|
DC_MASK00_RC204);
|
|
disp_write(base, DC_RC204, val);
|
|
|
|
val = reg_value(csc_param[0][3], 0, DC_SHIFT16_RC208,
|
|
DC_MASK16_RC208);
|
|
val = reg_value(csc_param[0][2], val, DC_SHIFT00_RC208,
|
|
DC_MASK00_RC208);
|
|
disp_write(base, DC_RC208, val);
|
|
|
|
val = reg_value(csc_param[0][5], 0, DC_SHIFT16_RC20C,
|
|
DC_MASK16_RC20C);
|
|
val = reg_value(csc_param[0][4], val, DC_SHIFT00_RC20C,
|
|
DC_MASK00_RC204C);
|
|
disp_write(base, DC_RC20C, val);
|
|
|
|
val = reg_value(csc_param[0][7], 0, DC_SHIFT16_RC210,
|
|
DC_MASK16_RC210);
|
|
val = reg_value(csc_param[0][6], val, DC_SHIFT00_RC210,
|
|
DC_MASK00_RC210);
|
|
disp_write(base, DC_RC210, val);
|
|
|
|
val = reg_value(csc_param[0][9], 0, DC_SHIFT16_RC214,
|
|
DC_MASK16_RC214);
|
|
val = reg_value(csc_param[0][8], val, DC_SHIFT00_RC214,
|
|
DC_MASK00_RC214);
|
|
disp_write(base, DC_RC214, val);
|
|
|
|
val = reg_value(csc_param[0][11], 0, DC_SHIFT16_RC218,
|
|
DC_MASK16_RC218);
|
|
val = reg_value(csc_param[0][10], val, DC_SHIFT00_RC218,
|
|
DC_MASK00_RC218);
|
|
disp_write(base, DC_RC218, val);
|
|
|
|
val = reg_value(csc_param[0][13], 0, DC_SHIFT16_RC21C,
|
|
DC_MASK16_RC21C);
|
|
val = reg_value(csc_param[0][12], val, DC_SHIFT00_RC21C,
|
|
DC_MASK00_RC21C);
|
|
disp_write(base, DC_RC21C, val);
|
|
|
|
val = reg_value(csc_param[0][14], 0, DC_SHIFT00_RC220,
|
|
DC_MASK00_RC220);
|
|
disp_write(base, DC_RC220, val);
|
|
}
|
|
|
|
static void dc_csc_init(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = reg_value(1, 0, DC_SHIFT00_RH000, DC_MASK00_RH000);
|
|
disp_write(base, DC_RH000, val);
|
|
|
|
val = reg_value(csc_param[0][1], 0, DC_SHIFT16_RH004,
|
|
DC_MASK16_RH004);
|
|
val = reg_value(csc_param[0][0], val, DC_SHIFT00_RH004,
|
|
DC_MASK00_RH004);
|
|
disp_write(base, DC_RH004, val);
|
|
|
|
val = reg_value(csc_param[0][3], 0, DC_SHIFT16_RH008,
|
|
DC_MASK16_RH008);
|
|
val = reg_value(csc_param[0][2], val, DC_SHIFT00_RH008,
|
|
DC_MASK00_RH008);
|
|
disp_write(base, DC_RH008, val);
|
|
|
|
val = reg_value(csc_param[0][5], 0, DC_SHIFT16_RH00C,
|
|
DC_MASK16_RH00C);
|
|
val = reg_value(csc_param[0][4], val, DC_SHIFT00_RH00C,
|
|
DC_MASK00_RH00C);
|
|
disp_write(base, DC_RH00C, val);
|
|
|
|
val = reg_value(csc_param[0][7], 0, DC_SHIFT16_RH010,
|
|
DC_MASK16_RH010);
|
|
val = reg_value(csc_param[0][6], val, DC_SHIFT00_RH010,
|
|
DC_MASK00_RH010);
|
|
disp_write(base, DC_RH010, val);
|
|
|
|
val = reg_value(csc_param[0][9], 0, DC_SHIFT16_RH014,
|
|
DC_MASK16_RH014);
|
|
val = reg_value(csc_param[0][8], val, DC_SHIFT00_RH014,
|
|
DC_MASK00_RH014);
|
|
disp_write(base, DC_RH014, val);
|
|
|
|
val = reg_value(csc_param[0][11], 0, DC_SHIFT16_RH018,
|
|
DC_MASK16_RH018);
|
|
val = reg_value(csc_param[0][10], val, DC_SHIFT00_RH018,
|
|
DC_MASK00_RH018);
|
|
disp_write(base, DC_RH018, val);
|
|
|
|
val = reg_value(csc_param[0][13], 0, DC_SHIFT16_RH01C,
|
|
DC_MASK16_RH01C);
|
|
val = reg_value(csc_param[0][12], val, DC_SHIFT00_RH01C,
|
|
DC_MASK00_RH01C);
|
|
disp_write(base, DC_RH01C, val);
|
|
|
|
val = reg_value(csc_param[0][14], 0, DC_SHIFT00_RH020,
|
|
DC_MASK00_RH020);
|
|
disp_write(base, DC_RH020, val);
|
|
|
|
dc_triggle_type |= DC_CSC_UPDATE;
|
|
}
|
|
static void dc_gamma_init(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = reg_value(1, 0, DC_SHIFT00_RI000, DC_MASK00_RI000);
|
|
disp_write(base, DC_RI000, val);
|
|
|
|
dc_triggle_type |= DC_GAMMA_UPDATE;
|
|
}
|
|
|
|
static void dc_dither_init(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = reg_value(1, 0, DC_SHIFT06_RI004, DC_MASK06_RI004);
|
|
val = reg_value(1, val, DC_SHIFT00_RI004, DC_MASK00_RI004);
|
|
disp_write(base, DC_RI004, val);
|
|
|
|
dc_triggle_type |= DC_DITHER_UPDATE;
|
|
}
|
|
|
|
static void dc_crc32_init(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = (dev->panel->timing->vsync_pol << DC_SHIFT09_RJ000) |
|
|
(dev->panel->timing->hsync_pol << DC_SHIFT08_RJ000) |
|
|
(dev->panel->timing->de_pol << DC_SHIFT07_RJ000) |
|
|
(1 << DC_SHIFT00_RJ000);
|
|
disp_write(base, DC_RJ000, val);
|
|
}
|
|
|
|
static void gen_crc_table(void)
|
|
{
|
|
register int i, j;
|
|
register unsigned int crc_accum;
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
crc_accum = ((unsigned int)i << 24);
|
|
for (j = 0; j < 8; j++) {
|
|
if (crc_accum & 0x80000000L)
|
|
crc_accum = (crc_accum << 1) ^ POLYNOMIAL;
|
|
else
|
|
crc_accum = (crc_accum << 1);
|
|
}
|
|
crc_table[i] = crc_accum;
|
|
}
|
|
}
|
|
|
|
static unsigned int update_crc(unsigned int crc_accum, void *data_blk_ptr,
|
|
int data_blk_size)
|
|
{
|
|
unsigned char *p;
|
|
p = (unsigned char *)data_blk_ptr;
|
|
|
|
register int i, j;
|
|
for (j = 0; j < data_blk_size; j++) {
|
|
i = ((int)(crc_accum >> 24) ^ *p) & 0xff;
|
|
crc_accum = (crc_accum << 8) ^ crc_table[i];
|
|
p++;
|
|
}
|
|
return crc_accum;
|
|
}
|
|
|
|
unsigned int sdrv_expect_crc32(int mode, struct surface *layer,
|
|
struct crc32block *crc32block)
|
|
{
|
|
unsigned int crc = 0;
|
|
unsigned int R;
|
|
unsigned int G;
|
|
unsigned int B;
|
|
unsigned int indata;
|
|
unsigned int *pindata;
|
|
unsigned int indata_b0;
|
|
unsigned int indata_b1;
|
|
unsigned int indata_b2;
|
|
unsigned int indata_b3;
|
|
unsigned int indata_MSB;
|
|
int stride = layer->src_stride[0];
|
|
int off;
|
|
int start_x = crc32block->cfg_start_x - layer->dst.x;
|
|
int start_y = crc32block->cfg_start_y - layer->dst.y;
|
|
int end_x = crc32block->cfg_end_x - layer->dst.x;
|
|
int end_y = crc32block->cfg_end_y - layer->dst.y;
|
|
char *addr = (char *)layer->addr[0];
|
|
gen_crc_table();
|
|
for (unsigned int i = start_y; i <= end_y; i++) {
|
|
for (unsigned int j = start_x; j <= end_x; j++) {
|
|
switch (layer->fmt) {
|
|
case COLOR_ARGB8888:
|
|
off = layer->src.x * 4 + stride * layer->src.y;
|
|
B = addr[off + i * stride + j * 4];
|
|
G = addr[off + i * stride + j * 4 + 1];
|
|
R = addr[off + i * stride + j * 4 + 2];
|
|
break;
|
|
case COLOR_BGRA8888:
|
|
off = layer->src.x * 4 + stride * layer->src.y;
|
|
R = addr[off + i * stride + j * 4 + 1];
|
|
G = addr[off + i * stride + j * 4 + 2];
|
|
B = addr[off + i * stride + j * 4 + 3];
|
|
break;
|
|
case COLOR_ABGR8888:
|
|
off = layer->src.x * 4 + stride * layer->src.y;
|
|
R = addr[off + i * stride + j * 4];
|
|
G = addr[off + i * stride + j * 4 + 1];
|
|
B = addr[off + i * stride + j * 4 + 2];
|
|
break;
|
|
case COLOR_RGB888:
|
|
off = layer->src.x * 3 + stride * layer->src.y;
|
|
B = addr[off + i * stride + j * 3];
|
|
G = addr[off + i * stride + j * 3 + 1];
|
|
R = addr[off + i * stride + j * 3 + 2];
|
|
break;
|
|
case COLOR_BGR888:
|
|
off = layer->src.x * 3 + stride * layer->src.y;
|
|
R = addr[off + i * stride + j * 3];
|
|
G = addr[off + i * stride + j * 3 + 1];
|
|
B = addr[off + i * stride + j * 3 + 2];
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
if (mode == CRC32_MODE_INTERNAL) {
|
|
B = (B << 2) | (B >> 6);
|
|
G = (G << 2) | (G >> 6);
|
|
R = (R << 2) | (R >> 6);
|
|
} else {
|
|
B = (B << 2);
|
|
G = (G << 2);
|
|
R = (R << 2);
|
|
}
|
|
|
|
indata = 0x00000000 | (R << 22) | (G << 12) | (B << 2);
|
|
indata_b0 = (indata & 0x000000FF) << 24;
|
|
indata_b1 = (indata & 0x0000FF00) << 8;
|
|
indata_b2 = (indata & 0x00FF0000) >> 8;
|
|
indata_b3 = (indata & 0xFF000000) >> 24;
|
|
indata_MSB = indata_b0 | indata_b1 | indata_b2 | indata_b3;
|
|
pindata = &indata_MSB;
|
|
crc = update_crc(crc, pindata, 4);
|
|
}
|
|
}
|
|
crc32block->expect_crc = crc;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void dc_crc32_set(struct dc_dev *dev)
|
|
{
|
|
unsigned int value;
|
|
unsigned long base = dev->base;
|
|
struct crc_info *info = dev->crc32;
|
|
|
|
for (int i = 0; i < info->block_num; i++) {
|
|
if (info->blocks[i].block_use) {
|
|
value = ((unsigned int)1 << DC_SHIFT31_RJ010) |
|
|
(info->blocks[i].cfg_start_y << DC_SHIFT16_RJ010) |
|
|
(info->blocks[i].cfg_start_x << DC_SHIFT00_RJ010);
|
|
disp_write(base, DC_RJ010(i), value);
|
|
|
|
value = (info->blocks[i].cfg_end_y << DC_SHIFT16_RJ014) |
|
|
(info->blocks[i].cfg_end_x << DC_SHIFT00_RJ014);
|
|
disp_write(base, DC_RJ014(i), value);
|
|
|
|
value = info->blocks[i].expect_crc;
|
|
disp_write(base, DC_RJ018(i), value);
|
|
} else {
|
|
disp_write(base, DC_RJ010(i), 0);
|
|
}
|
|
}
|
|
dc_triggle_type |= DC_CRC_UPDATE;
|
|
}
|
|
|
|
static int crc32_check_and_calc(struct dc_dev *dev, struct post_cfg *post)
|
|
{
|
|
struct crc32block *block;
|
|
struct surface *layer;
|
|
int start_x, start_y, end_x, end_y;
|
|
int flag, b_en;
|
|
|
|
for (int i = 0; i < dev->crc32->block_num; i++) {
|
|
flag = 0;
|
|
block = &dev->crc32->blocks[i];
|
|
|
|
if (!block->block_use)
|
|
continue;
|
|
|
|
for (int k = 0; k < post->num_layers; k++) {
|
|
layer = &post->layers[i];
|
|
if (!layer->en)
|
|
continue;
|
|
|
|
start_x = layer->dst.x;
|
|
start_y = layer->dst.y;
|
|
end_x = layer->dst.x + layer->dst.w;
|
|
end_y = layer->dst.y + layer->dst.h;
|
|
|
|
if ((start_x <= block->cfg_start_x) &&
|
|
(start_y <= block->cfg_start_y) &&
|
|
(end_x >= block->cfg_end_x) && (end_y >= block->cfg_end_y)) {
|
|
if (layer->id == PIPE_TYPE_SPIPE)
|
|
flag |= 1;
|
|
else
|
|
flag |= 2;
|
|
}
|
|
}
|
|
|
|
switch (flag) {
|
|
case 1:
|
|
for (int k = 0; k < post->num_layers; k++) {
|
|
layer = &post->layers[i];
|
|
if (layer->id == PIPE_TYPE_SPIPE) {
|
|
b_en = sdrv_expect_crc32(dev->crc32->mode, layer, block);
|
|
if (b_en == 0)
|
|
block->block_use = 0;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
for (int k = 0; k < post->num_layers; k++) {
|
|
layer = &post->layers[i];
|
|
if (layer->id == PIPE_TYPE_GPIPE) {
|
|
b_en = sdrv_expect_crc32(dev->crc32->mode, layer, block);
|
|
if (b_en == 0)
|
|
block->block_use = 0;
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void set_tcon_ctrl_en(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
static int enable = 0;
|
|
|
|
if (!enable) {
|
|
enable = 1;
|
|
val = disp_read(base, DC_RG010);
|
|
val = reg_value(1, val, DC_SHIFT00_RG010, DC_MASK00_RG010);
|
|
disp_write(base, DC_RG010, val);
|
|
}
|
|
}
|
|
|
|
static int dc_plane_frm_comp_set(struct dc_dev *dev, struct surface *input)
|
|
{
|
|
unsigned int compval;
|
|
unsigned int frmc_val;
|
|
unsigned char abits, ybits, ubits, vbits;
|
|
unsigned char swap;
|
|
unsigned char comp_swap;
|
|
unsigned char is_yuv;
|
|
unsigned char is_uvswap;
|
|
unsigned char uv_mode;
|
|
unsigned char data_mode;
|
|
unsigned char buf_fmt;
|
|
unsigned long base = dev->base;
|
|
|
|
abits = COLOR_GET_A_BITS_NUM(input->fmt);
|
|
ybits = COLOR_GET_Y_BITS_NUM(input->fmt);
|
|
ubits = COLOR_GET_U_BITS_NUM(input->fmt);
|
|
vbits = COLOR_GET_V_BITS_NUM(input->fmt);
|
|
compval = reg_value(vbits, 0, DC_SHIFT24_RC000, DC_MASK24_RC000);
|
|
compval = reg_value(ubits, compval, DC_SHIFT16_RC000, DC_MASK16_RC000);
|
|
compval = reg_value(ybits, compval, DC_SHIFT08_RC000, DC_MASK08_RC000);
|
|
compval = reg_value(abits, compval, DC_SHIFT00_RC000, DC_MASK00_RC000);
|
|
|
|
swap = COLOR_GET_SWAP(input->fmt);
|
|
comp_swap = COLOR_GET_COMP_SWAP(input->fmt);
|
|
is_yuv = COLOR_GET_IS_YUV(input->fmt);
|
|
is_uvswap = COLOR_GET_IS_UV_SWAP(input->fmt);
|
|
uv_mode = COLOR_GET_UV_MODE(input->fmt);
|
|
if (!input->rle.en)
|
|
data_mode = COLOR_GET_DATA_MODE(input->fmt);
|
|
else
|
|
data_mode = RLE_COMPR_MODE;
|
|
buf_fmt = COLOR_GET_BUF_FMT(input->fmt);
|
|
|
|
frmc_val = reg_value(swap, 0, DC_SHIFT16_RC004, DC_MASK16_RC004);
|
|
frmc_val = reg_value(comp_swap, frmc_val, DC_SHIFT12_RC004, DC_MASK12_RC004);
|
|
frmc_val = reg_value(is_yuv, frmc_val, DC_SHIFT07_RC004, DC_MASK07_RC004);
|
|
frmc_val = reg_value(is_uvswap, frmc_val, DC_SHIFT06_RC004, DC_MASK06_RC004);
|
|
frmc_val = reg_value(uv_mode, frmc_val, DC_SHIFT04_RC004, DC_MASK04_RC004);
|
|
frmc_val = reg_value(data_mode, frmc_val, DC_SHIFT02_RC004, DC_MASK02_RC004);
|
|
frmc_val = reg_value(buf_fmt, frmc_val, DC_SHIFT00_RC004, DC_MASK00_RC004);
|
|
|
|
if (input->id == PIPE_TYPE_SPIPE) {
|
|
disp_write(base, DC_RD000(0), compval);
|
|
disp_write(base, DC_RD004(0), frmc_val);
|
|
} else if (input->id == PIPE_TYPE_GPIPE) {
|
|
disp_write(base, DC_RC000, compval);
|
|
disp_write(base, DC_RC004, frmc_val);
|
|
} else {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dc_safety_init(struct dc_dev *dev)
|
|
{
|
|
unsigned int val, compval, frmc_val;
|
|
unsigned char comp_swap, is_yuv, is_uvswap;
|
|
unsigned char uv_mode, data_mode, buf_fmt;
|
|
unsigned char abits, ybits, ubits, vbits;
|
|
unsigned int input_fmt = COLOR_RGB565;
|
|
unsigned int src_size;
|
|
unsigned long base = dev->base;
|
|
struct display_timing *timing = dev->panel->timing;
|
|
|
|
abits = COLOR_GET_A_BITS_NUM(input_fmt);
|
|
ybits = COLOR_GET_Y_BITS_NUM(input_fmt);
|
|
ubits = COLOR_GET_U_BITS_NUM(input_fmt);
|
|
vbits = COLOR_GET_V_BITS_NUM(input_fmt);
|
|
compval = reg_value(vbits, 0, DC_SHIFT24_RC000, DC_MASK24_RC000);
|
|
compval = reg_value(ubits, compval, DC_SHIFT16_RC000, DC_MASK16_RC000);
|
|
compval = reg_value(ybits, compval, DC_SHIFT08_RC000, DC_MASK08_RC000);
|
|
compval = reg_value(abits, compval, DC_SHIFT00_RC000, DC_MASK00_RC000);
|
|
|
|
comp_swap = COLOR_GET_COMP_SWAP(input_fmt);
|
|
is_yuv = COLOR_GET_IS_YUV(input_fmt);
|
|
is_uvswap = COLOR_GET_IS_UV_SWAP(input_fmt);
|
|
uv_mode = COLOR_GET_UV_MODE(input_fmt);
|
|
data_mode = COLOR_GET_DATA_MODE(input_fmt);
|
|
buf_fmt = COLOR_GET_BUF_FMT(input_fmt);
|
|
frmc_val = reg_value(comp_swap, 0, DC_SHIFT12_RC004, DC_MASK12_RC004);
|
|
frmc_val = reg_value(is_yuv, frmc_val, DC_SHIFT07_RC004, DC_MASK07_RC004);
|
|
frmc_val = reg_value(is_uvswap, frmc_val, DC_SHIFT06_RC004, DC_MASK06_RC004);
|
|
frmc_val = reg_value(uv_mode, frmc_val, DC_SHIFT04_RC004, DC_MASK04_RC004);
|
|
frmc_val = reg_value(data_mode, frmc_val, DC_SHIFT02_RC004, DC_MASK02_RC004);
|
|
frmc_val = reg_value(buf_fmt, frmc_val, DC_SHIFT00_RC004, DC_MASK00_RC004);
|
|
|
|
disp_write(base, DC_RD000(1), compval);
|
|
disp_write(base, DC_RD004(1), frmc_val);
|
|
|
|
/*pipe related*/
|
|
src_size =
|
|
reg_value(warning_image.width - 1, 0, DC_SHIFT00_RC008, DC_MASK00_RC008);
|
|
src_size = reg_value(warning_image.height - 1, src_size, DC_SHIFT16_RC008,
|
|
DC_MASK16_RC008);
|
|
disp_write(base, DC_RD008(1), src_size);
|
|
disp_write(base, DC_RD00C(1), (unsigned long)warning_image.y);
|
|
disp_write(base, DC_RD010(1), 0);
|
|
disp_write(base, DC_RD02C(1), warning_image.width * 2 - 1);
|
|
disp_write(base, DC_RD040(1), 0);
|
|
|
|
/*S_SP Triggle*/
|
|
disp_write(base, DC_RDF00(1), 0x1);
|
|
|
|
/*mlc related*/
|
|
|
|
disp_write(base, DC_RF230, 0x3ff);
|
|
|
|
disp_write(base, DC_RF004(MLC_LAYER_SP),
|
|
(timing->hactive - warning_image.width) / 2);
|
|
disp_write(base, DC_RF008(MLC_LAYER_SP),
|
|
(timing->vactive - warning_image.height) / 2);
|
|
disp_write(base, DC_RF00C(MLC_LAYER_SP), src_size);
|
|
|
|
disp_write(base, DC_RF018(MLC_LAYER_SP), 0xFF);
|
|
|
|
val = disp_read(base, DC_RF000(MLC_LAYER_SP));
|
|
val = reg_value(1, val, DC_SHIFT02_RE000, DC_MASK02_RE000);
|
|
val = reg_value(1, val, DC_SHIFT00_RE000, DC_MASK00_RE000);
|
|
disp_write(base, DC_RF000(MLC_LAYER_SP), val);
|
|
|
|
/*set z-order*/
|
|
disp_write(base, DC_RF200(MLC_PATH_SP), 0x10001);
|
|
|
|
/*SF_FLC_CTRL Triggle*/
|
|
val = reg_value(1, 0, DC_SHIFT02_RA004, DC_MASK02_RA004);
|
|
val = reg_value(1, val, DC_SHIFT01_RA004, DC_MASK01_RA004);
|
|
val = reg_value(1, val, DC_SHIFT00_RA004, DC_MASK00_RA004);
|
|
disp_write(base, DC_RA100, val);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dc_reset(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = disp_read(base, DC_RA000);
|
|
val = reg_value(1, val, DC_SHIFT31_RA000, DC_MASK31_RA000);
|
|
disp_write(base, DC_RA000, val);
|
|
|
|
udelay(10);
|
|
|
|
val = reg_value(0, val, DC_SHIFT31_RA000, DC_MASK31_RA000);
|
|
disp_write(base, DC_RA000, val);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dc_gpipe_reset(struct dc_dev *dev)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = disp_read(base, DC_RCE00);
|
|
val = reg_value(1, val, DC_SHIFT00_RCE00, DC_MASK00_RCE00);
|
|
disp_write(base, DC_RCE00, val);
|
|
|
|
udelay(10);
|
|
|
|
val = reg_value(0, val, DC_SHIFT00_RCE00, DC_MASK00_RCE00);
|
|
disp_write(base, DC_RCE00, val);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dc_csi_mask_ratio_set(struct dc_dev *dev, int mask_count, int ratio)
|
|
{
|
|
unsigned long base = dev->base;
|
|
unsigned int val;
|
|
|
|
val = disp_read(base, DC_RG500);
|
|
val = reg_value(ratio, val, DC_SHIFT04_RG500, DC_MASK04_RG500);
|
|
val = reg_value(mask_count, val, DC_SHIFT02_RG500, DC_MASK02_RG500);
|
|
disp_write(base, DC_RG500, val);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dc_csi_timing_dectet_enable(struct dc_dev *dev, bool enable)
|
|
{
|
|
unsigned long base = dev->base;
|
|
|
|
if (enable) {
|
|
disp_write(base, DC_RG504, 1);
|
|
} else {
|
|
disp_write(base, DC_RG504, 0);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dc_init(struct dc_dev *dev)
|
|
{
|
|
dc_reset(dev);
|
|
dc_ms_mode(dev);
|
|
dc_irq_disable(dev);
|
|
dc_rdma_init(dev);
|
|
dc_tcon_init(dev);
|
|
dc_mlc_init(dev);
|
|
dc_spipe_init(dev);
|
|
dc_gpipe_init(dev);
|
|
dc_csc_init(dev);
|
|
dc_gamma_init(dev);
|
|
dc_dither_init(dev);
|
|
dc_irq_init(dev);
|
|
dc_crc32_init(dev);
|
|
dc_safety_init(dev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool fmt_is_spipe_support(unsigned int fmt)
|
|
{
|
|
switch (fmt) {
|
|
case COLOR_RGB565:
|
|
case COLOR_BGR565:
|
|
case COLOR_ARGB4444:
|
|
case COLOR_BGRA4444:
|
|
case COLOR_ARGB1555:
|
|
case COLOR_BGRA5551:
|
|
case COLOR_ABGR1555:
|
|
case COLOR_RGB666:
|
|
case COLOR_BGR666:
|
|
case COLOR_RGB888:
|
|
case COLOR_BGR888:
|
|
case COLOR_ARGB8888:
|
|
case COLOR_BGRA8888:
|
|
case COLOR_ARGB2101010:
|
|
case COLOR_BGRA1010102:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static int dc_offset_to_addr(struct surface *input)
|
|
{
|
|
unsigned char uv_mode = COLOR_GET_UV_MODE(input->fmt);
|
|
unsigned char n_planes = COLOR_GET_PLANE_COUNT(input->fmt);
|
|
|
|
if (n_planes == 1)
|
|
return 0;
|
|
|
|
switch (uv_mode) {
|
|
case UV_YUV422:
|
|
if (n_planes == 2) {
|
|
input->addr[0] +=
|
|
input->start.y * input->src_stride[0] + input->start.x;
|
|
input->addr[1] +=
|
|
input->start.y * input->src_stride[1] + input->start.x;
|
|
}
|
|
if (n_planes == 3) {
|
|
input->addr[0] +=
|
|
input->start.y * input->src_stride[0] + input->start.x;
|
|
input->addr[1] +=
|
|
input->start.y * input->src_stride[1] + input->start.x / 2;
|
|
input->addr[2] +=
|
|
input->start.y * input->src_stride[2] + input->start.x / 2;
|
|
}
|
|
break;
|
|
case UV_YUV420:
|
|
if (n_planes == 2) {
|
|
input->addr[0] +=
|
|
input->start.y * input->src_stride[0] + input->start.x;
|
|
input->addr[1] +=
|
|
input->start.y / 2 * input->src_stride[1] + input->start.x;
|
|
}
|
|
if (n_planes == 3) {
|
|
input->addr[0] +=
|
|
input->start.y * input->src_stride[0] + input->start.x;
|
|
input->addr[1] +=
|
|
input->start.y / 2 * input->src_stride[1] + input->start.x / 2;
|
|
input->addr[2] +=
|
|
input->start.y / 2 * input->src_stride[2] + input->start.x / 2;
|
|
}
|
|
break;
|
|
case UV_YUV440:
|
|
if (n_planes == 2) {
|
|
input->addr[0] +=
|
|
input->start.y * input->src_stride[0] + input->start.x;
|
|
input->addr[1] +=
|
|
input->start.y * input->src_stride[1] + input->start.x * 2;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void dc_clear_layers(struct dc_dev *dev, uint8_t mask, uint8_t z_order)
|
|
{
|
|
int val;
|
|
unsigned long base = dev->base;
|
|
int zorder = z_order + 1;
|
|
|
|
switch (mask) {
|
|
case CLEAR_SPIPE_LAYER:
|
|
/*Disable Layer*/
|
|
val = disp_read(base, DC_RE000(MLC_LAYER_SP));
|
|
val = reg_value(0, val, DC_SHIFT00_RE000, DC_MASK00_RE000);
|
|
disp_write(base, DC_RE000(MLC_LAYER_SP), val);
|
|
|
|
/*Disable Path*/
|
|
val = disp_read(base, DC_RE200(MLC_PATH_SP));
|
|
val = reg_value(0xF, val, DC_SHIFT00_RE200, DC_MASK00_RE200);
|
|
disp_write(base, DC_RE200(MLC_PATH_SP), val);
|
|
|
|
val = disp_read(base, DC_RE200(zorder));
|
|
val = reg_value(0xF, val, DC_SHIFT16_RE200, DC_MASK16_RE200);
|
|
disp_write(base, DC_RE200(zorder), val);
|
|
|
|
dc_triggle_type |= DC_SP_UPDATE;
|
|
dc_triggle_type |= DC_MLC_UPDATE;
|
|
|
|
break;
|
|
case CLEAR_GPIPE_LAYER:
|
|
/*Disable Layer*/
|
|
val = disp_read(base, DC_RE000(MLC_LAYER_GP));
|
|
val = reg_value(0, val, DC_SHIFT00_RE000, DC_MASK00_RE000);
|
|
disp_write(base, DC_RE000(MLC_LAYER_GP), val);
|
|
|
|
/*Disable Path*/
|
|
val = disp_read(base, DC_RE200(MLC_PATH_GP));
|
|
val = reg_value(0xF, val, DC_SHIFT00_RE200, DC_MASK00_RE200);
|
|
disp_write(base, DC_RE200(MLC_PATH_GP), val);
|
|
|
|
val = disp_read(base, DC_RE200(zorder));
|
|
val = reg_value(0xF, val, DC_SHIFT16_RE200, DC_MASK16_RE200);
|
|
disp_write(base, DC_RE200(zorder), val);
|
|
|
|
dc_triggle_type |= DC_GP_UPDATE;
|
|
dc_triggle_type |= DC_MLC_UPDATE;
|
|
|
|
break;
|
|
case CLEAR_ALL_LAYERS:
|
|
for (int i = 0; i < MLC_LAYER_NUM; i++) {
|
|
val = disp_read(base, DC_RE000(i));
|
|
val = reg_value(0, val, DC_SHIFT00_RE000, DC_MASK00_RE000);
|
|
disp_write(base, DC_RE000(i), val);
|
|
}
|
|
|
|
disp_write(base, DC_RE200(1), 0xF000F);
|
|
disp_write(base, DC_RE200(2), 0xF000F);
|
|
|
|
dc_triggle_type |= DC_SP_UPDATE;
|
|
dc_triggle_type |= DC_GP_UPDATE;
|
|
dc_triggle_type |= DC_MLC_UPDATE;
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int dc_update_layer(struct dc_dev *dev, struct surface *layer)
|
|
{
|
|
unsigned int val;
|
|
unsigned char nplanes;
|
|
unsigned int src_size;
|
|
unsigned int src_offset;
|
|
unsigned long base = dev->base;
|
|
unsigned char is_yuv = 0;
|
|
int zorder;
|
|
|
|
if (!layer) {
|
|
return -1;
|
|
}
|
|
zorder = layer->z_order + 1;
|
|
|
|
nplanes = COLOR_GET_PLANE_COUNT(layer->fmt);
|
|
dc_plane_frm_comp_set(dev, layer);
|
|
|
|
src_size =
|
|
reg_value(layer->start.w - 1, 0, DC_SHIFT00_RC008, DC_MASK00_RC008);
|
|
src_size = reg_value(layer->start.h - 1, src_size, DC_SHIFT16_RC008,
|
|
DC_MASK16_RC008);
|
|
|
|
if (nplanes == 1) {
|
|
src_offset = reg_value(layer->start.x, 0, DC_SHIFT00_RC040, DC_MASK00_RC040);
|
|
src_offset =
|
|
reg_value(layer->start.y, src_offset, DC_SHIFT16_RC040, DC_MASK16_RC040);
|
|
} else {
|
|
src_offset = 0;
|
|
}
|
|
|
|
dc_offset_to_addr(layer);
|
|
|
|
dev->last_zorder[layer->id] = zorder;
|
|
|
|
if (layer->id == PIPE_TYPE_SPIPE) {
|
|
/*pipe related*/
|
|
disp_write(base, DC_RD008(0), src_size);
|
|
disp_write(base, DC_RD00C(0), get_l_addr(layer->addr[0]));
|
|
disp_write(base, DC_RD010(0), get_h_addr(layer->addr[1]));
|
|
disp_write(base, DC_RD02C(0), layer->src_stride[0] - 1);
|
|
disp_write(base, DC_RD040(0), src_offset);
|
|
dc_triggle_type |= DC_SP_UPDATE;
|
|
|
|
/*mlc related*/
|
|
disp_write(base, DC_RE004(MLC_LAYER_SP), layer->dst.x);
|
|
disp_write(base, DC_RE008(MLC_LAYER_SP), layer->dst.y);
|
|
disp_write(base, DC_RE00C(MLC_LAYER_SP), src_size);
|
|
|
|
if (layer->alpha_en)
|
|
disp_write(base, DC_RE018(MLC_LAYER_SP), layer->alpha);
|
|
|
|
val = disp_read(base, DC_RE000(MLC_LAYER_SP));
|
|
val = reg_value(layer->alpha_en, val, DC_SHIFT02_RE000,
|
|
DC_MASK02_RE000);
|
|
val = reg_value(1, val, DC_SHIFT00_RE000, DC_MASK00_RE000);
|
|
disp_write(base, DC_RE000(MLC_LAYER_SP), val);
|
|
|
|
/*set z-order*/
|
|
val = disp_read(base, DC_RE200(MLC_PATH_SP));
|
|
val = reg_value(zorder, val, DC_SHIFT00_RE200, DC_MASK00_RE200);
|
|
disp_write(base, DC_RE200(MLC_PATH_SP), val);
|
|
|
|
val = disp_read(base, DC_RE200(zorder));
|
|
val = reg_value(0x1, val, DC_SHIFT16_RE200, DC_MASK16_RE200);
|
|
disp_write(base, DC_RE200(zorder), val);
|
|
|
|
if (!layer->rle.en) {
|
|
val = reg_value(0, 0, DC_SHIFT00_RD120, DC_MASK00_RD120);
|
|
disp_write(base, DC_RD120(0), val);
|
|
} else {
|
|
val = reg_value(layer->rle.data_size, 0, DC_SHIFT01_RD120,
|
|
DC_MASK01_RD120);
|
|
val = reg_value(layer->rle.en, val, DC_SHIFT00_RD120, DC_MASK00_RD120);
|
|
disp_write(base, DC_RD120(0), val);
|
|
|
|
disp_write(base, DC_RD100(0), layer->rle.y_len);
|
|
disp_write(base, DC_RD110(0), layer->rle.y_checksum);
|
|
}
|
|
|
|
dc_triggle_type |= DC_MLC_UPDATE;
|
|
} else if (layer->id == PIPE_TYPE_GPIPE) {
|
|
/*pipe related*/
|
|
disp_write(base, DC_RC008, src_size);
|
|
disp_write(base, DC_RC00C, get_l_addr(layer->addr[0]));
|
|
disp_write(base, DC_RC010, get_h_addr(layer->addr[0]));
|
|
disp_write(base, DC_RC02C, layer->src_stride[0] - 1);
|
|
disp_write(base, DC_RC040, src_offset);
|
|
if (nplanes > 1) {
|
|
disp_write(base, DC_RC014, get_l_addr(layer->addr[1]));
|
|
disp_write(base, DC_RC018, get_h_addr(layer->addr[1]));
|
|
disp_write(base, DC_RC030, layer->src_stride[1] - 1);
|
|
}
|
|
if (nplanes > 2) {
|
|
disp_write(base, DC_RC01C, get_l_addr(layer->addr[2]));
|
|
disp_write(base, DC_RC020, get_h_addr(layer->addr[2]));
|
|
disp_write(base, DC_RC034, layer->src_stride[2] - 1);
|
|
}
|
|
is_yuv = COLOR_GET_IS_YUV(layer->fmt);
|
|
val = disp_read(base, DC_RC044);
|
|
val = reg_value(is_yuv, val, DC_SHIFT31_RC044, DC_MASK31_RC044);
|
|
val = reg_value(is_yuv ? 0 : 1, val, DC_SHIFT00_RC044,
|
|
DC_MASK00_RC044);
|
|
disp_write(base, DC_RC044, val);
|
|
|
|
val = disp_read(base, DC_RC200);
|
|
val = reg_value(is_yuv ? 0 : 1, val, DC_SHIFT00_RC200,
|
|
DC_MASK00_RC200);
|
|
disp_write(base, DC_RC200, val);
|
|
|
|
dc_triggle_type |= DC_GP_UPDATE;
|
|
|
|
/*mlc related*/
|
|
disp_write(base, DC_RE004(MLC_LAYER_GP), layer->dst.x);
|
|
disp_write(base, DC_RE008(MLC_LAYER_GP), layer->dst.y);
|
|
disp_write(base, DC_RE00C(MLC_LAYER_GP), src_size);
|
|
|
|
if (layer->alpha_en)
|
|
disp_write(base, DC_RE018(MLC_LAYER_GP), layer->alpha);
|
|
|
|
val = disp_read(base, DC_RE000(MLC_LAYER_GP));
|
|
val = reg_value(layer->alpha_en, val, DC_SHIFT02_RE000,
|
|
DC_MASK02_RE000);
|
|
val = reg_value(1, val, DC_SHIFT00_RE000, DC_MASK00_RE000);
|
|
disp_write(base, DC_RE000(MLC_LAYER_GP), val);
|
|
|
|
/*set z-order*/
|
|
val = disp_read(base, DC_RE200(MLC_PATH_GP));
|
|
val = reg_value(zorder, val, DC_SHIFT00_RE200, DC_MASK00_RE200);
|
|
disp_write(base, DC_RE200(MLC_PATH_GP), val);
|
|
|
|
val = disp_read(base, DC_RE200(zorder));
|
|
val = reg_value(0x2, val, DC_SHIFT16_RE200, DC_MASK16_RE200);
|
|
disp_write(base, DC_RE200(zorder), val);
|
|
|
|
dc_triggle_type |= DC_MLC_UPDATE;
|
|
} else {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dc_update(struct dc_dev *dev, struct post_cfg *post)
|
|
{
|
|
int ret;
|
|
|
|
if (post->num_layers > PIPE_TYPE_NUM) {
|
|
return -1;
|
|
}
|
|
|
|
if (dev->crc32) {
|
|
crc32_check_and_calc(dev, post);
|
|
dc_crc32_set(dev);
|
|
}
|
|
|
|
for (unsigned int i = 0; i < post->num_layers; i++) {
|
|
if (!post->layers[i].en) {
|
|
if (post->layers[i].dirty)
|
|
dc_clear_layers(dev, 1 << post->layers[i].id,
|
|
dev->last_zorder[post->layers[i].id]);
|
|
|
|
continue;
|
|
}
|
|
|
|
ret = dc_update_layer(dev, &post->layers[i]);
|
|
if (ret < 0) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void dc_vsync_enable(struct dc_dev *dev, bool enable)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = disp_read(base, DC_RA020);
|
|
val = reg_value(enable ? 0 : 1, val, DC_SHIFT03_RA02X, DC_MASK03_RA02X);
|
|
disp_write(base, DC_RA020, val);
|
|
}
|
|
|
|
void dc_dect_done_enable(struct dc_dev *dev, bool enable)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = disp_read(base, DC_RA020);
|
|
val = reg_value(enable ? 0 : 1, val, DC_SHIFT28_RA02X,
|
|
DC_MASK28_RA02X);
|
|
disp_write(base, DC_RA020, val);
|
|
}
|
|
|
|
void dc_vsync_delay_done_enable(struct dc_dev *dev, bool enable)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = disp_read(base, DC_RA020);
|
|
val = reg_value(enable ? 0 : 1, val, DC_SHIFT29_RA02X,
|
|
DC_MASK29_RA02X);
|
|
disp_write(base, DC_RA020, val);
|
|
}
|
|
|
|
static void tcon_auto_adj_enable(struct dc_dev *dev, bool enable)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
DISPSS_LOG_FUNC();
|
|
|
|
val = disp_read(base, DC_RG500);
|
|
val = reg_value(enable ? 1 : 0, val, DC_SHIFT08_RG500, DC_MASK08_RG500);
|
|
disp_write(base, DC_RG500, val);
|
|
|
|
dc_csi_timing_dectet_enable(dev, enable);
|
|
}
|
|
|
|
void dc_short_convt(struct dc_dev *dev, int is_up, int delta)
|
|
{
|
|
unsigned long base = dev->base;
|
|
int val, old;
|
|
int lmax, remainder;
|
|
|
|
lmax = delta / 4;
|
|
remainder = delta % 4;
|
|
|
|
if (remainder)
|
|
lmax += 1;
|
|
|
|
for (int i = 0; i < lmax; i++) {
|
|
while (1) {
|
|
val = disp_read(base, DC_RA024);
|
|
disp_write(base, DC_RA024, val);
|
|
if (val & DC_MASK28_RA02X)
|
|
break;
|
|
}
|
|
|
|
val = disp_read(base, DC_RG500);
|
|
if (is_up && (i == 0))
|
|
old = (val >> DC_SHIFT16_RG500) + t_timing.vtol;
|
|
else
|
|
old = val >> DC_SHIFT16_RG500;
|
|
|
|
if (i < (lmax - 1))
|
|
val = reg_value(old - 4, val, DC_SHIFT16_RG500, DC_MASK16_RG500);
|
|
else
|
|
val = reg_value(old - remainder, val, DC_SHIFT16_RG500,
|
|
DC_MASK16_RG500);
|
|
disp_write(base, DC_RG500, val);
|
|
|
|
dc_triggle_type |= DC_TCON_UPDATE;
|
|
dc_triggle(dev);
|
|
}
|
|
}
|
|
|
|
static void tcon_csi_delay_set(struct dc_dev *dev)
|
|
{
|
|
unsigned long base = dev->base;
|
|
int t1, t2, t3, t4, dly_pre, dly_cur;
|
|
int val, htol, vfp;
|
|
int is_up;
|
|
|
|
DISPSS_LOG_FUNC();
|
|
|
|
htol = t_timing.htol;
|
|
vfp = t_timing.vtol - t_timing.vact - t_timing.vsbp;
|
|
|
|
val = disp_read(base, DC_RG518);
|
|
if (((val + 1) % htol) == 0)
|
|
t1 = (val + 1) / htol;
|
|
else
|
|
t1 = (val + 1) / htol + 1;
|
|
|
|
t3 = dev->app.buf_size_num_lines;
|
|
dly_pre = disp_read(base, DC_RG500) >> DC_SHIFT16_RG500;
|
|
t2 = disp_read(base, DC_RG520);
|
|
t4 = t1 + dev->app.t_delta + t3 + vfp;
|
|
if (t4 > t2) {
|
|
dly_cur = (t4 - t2) + dly_pre;
|
|
val = disp_read(base, DC_RG500);
|
|
val = reg_value(dly_cur, val, DC_SHIFT16_RG500, DC_MASK16_RG500);
|
|
disp_write(base, DC_RG500, val);
|
|
dc_triggle_type |= DC_TCON_UPDATE;
|
|
dc_triggle(dev);
|
|
} else {
|
|
if ((t2 - t4) <= dly_pre) {
|
|
is_up = 0;
|
|
} else {
|
|
is_up = 1;
|
|
}
|
|
dc_short_convt(dev, is_up, t2 - t4);
|
|
}
|
|
}
|
|
|
|
static int get_dt(struct dc_dev *dev)
|
|
{
|
|
unsigned long base = dev->base;
|
|
int val, htol, vfp;
|
|
int t1, t2, t3, t4;
|
|
|
|
htol = t_timing.htol;
|
|
vfp = t_timing.vtol - t_timing.vact - t_timing.vsbp;
|
|
|
|
val = disp_read(base, DC_RG518);
|
|
if (((val + 1) % htol) == 0)
|
|
t1 = (val + 1) / htol;
|
|
else
|
|
t1 = (val + 1) / htol + 1;
|
|
|
|
t3 = dev->app.buf_size_num_lines;
|
|
t2 = disp_read(base, DC_RG520);
|
|
t4 = t1 + dev->app.t_delta + t3 + vfp;
|
|
|
|
return (t2 - t4);
|
|
}
|
|
|
|
static void tcon_csi_delay_set2(struct dc_dev *dev)
|
|
{
|
|
const int pll_lvds_base = 0xF30a0000;
|
|
const int reg_n = 0x4;
|
|
int dt, n;
|
|
|
|
DISPSS_LOG_FUNC();
|
|
|
|
n = disp_read(pll_lvds_base, reg_n);
|
|
dt = get_dt(dev);
|
|
while (!((dt < 0) ? (dt > -1) : (dt < 1))) {
|
|
if (dt < 0) {
|
|
disp_write(pll_lvds_base, reg_n, n - 1);
|
|
} else {
|
|
disp_write(pll_lvds_base, reg_n, n + 1);
|
|
}
|
|
udelay(1);
|
|
dt = get_dt(dev);
|
|
}
|
|
disp_write(pll_lvds_base, reg_n, n);
|
|
}
|
|
|
|
static int dc_irq_handler(uint32_t irq, void *arg)
|
|
{
|
|
struct dc_dev *dev = (struct dc_dev *)arg;
|
|
unsigned long base = dev->base;
|
|
unsigned int value;
|
|
|
|
value = disp_read(base, DC_RA024);
|
|
disp_write(base, DC_RA024, value);
|
|
|
|
if (value & DC_MASK04_RA02X) {
|
|
if (dev->vsync_callback)
|
|
dev->vsync_callback();
|
|
}
|
|
|
|
if (value & DC_MASK05_RA02X) {
|
|
DISPSS_LOG_INFO("dc tcon underrun");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dc_set_tcon_after_detect(struct dc_dev *dev, int ratio_num)
|
|
{
|
|
unsigned long base = dev->base;
|
|
int csi_vtol;
|
|
int val;
|
|
|
|
timing_to_tcon_timing(dev->panel->timing, &t_timing);
|
|
|
|
/* csi_vtol && csi_vysnc unit is dc pixel clock. */
|
|
csi_vtol = disp_read(base, DC_RG514) + 1;
|
|
|
|
if ((csi_vtol % t_timing.htol) == 0) {
|
|
t_timing.vtol = csi_vtol / t_timing.htol;
|
|
} else {
|
|
t_timing.vtol = csi_vtol / t_timing.htol + 1;
|
|
}
|
|
|
|
t_timing.vsbp = (t_timing.vtol - t_timing.vact) / 3 * 2;
|
|
t_timing.vsync = (t_timing.vtol - t_timing.vact) / 3;
|
|
|
|
/* Vertical active size && total vertical size in lines. */
|
|
val = reg_value(t_timing.vact - 1, 0, DC_SHIFT16_RG008, DC_MASK16_RG008);
|
|
val = reg_value(t_timing.vtol - 1, val, DC_SHIFT00_RG008, DC_MASK00_RG008);
|
|
disp_write(base, DC_RG008, val);
|
|
|
|
/* Vertical back porch size && width of vsync pulse in lines. */
|
|
val = reg_value(t_timing.vsbp - 1, 0, DC_SHIFT16_RG00C, DC_MASK16_RG00C);
|
|
val = reg_value(t_timing.vsync - 1, val, DC_SHIFT00_RG00C, DC_MASK00_RG00C);
|
|
disp_write(base, DC_RG00C, val);
|
|
|
|
disp_write(base, DC_RG600, 1);
|
|
|
|
dc_triggle_type |= DC_TCON_UPDATE;
|
|
}
|
|
|
|
void dc_hsdk_enable(struct dc_dev *dev, int mode, bool enable)
|
|
{
|
|
unsigned int val;
|
|
unsigned long base = dev->base;
|
|
|
|
val = reg_value(mode, 0, DC_SHIFT01_RCD00, DC_MASK01_RCD00);
|
|
val = reg_value(enable ? 1 : 0, val, DC_SHIFT00_RCD00, DC_MASK00_RCD00);
|
|
disp_write(base, DC_RCD00, val);
|
|
dc_triggle_type |= DC_GP_UPDATE;
|
|
|
|
disp_write(base, DC_RG024(4), enable ? 1 : 0);
|
|
dc_triggle_type |= DC_TCON_UPDATE;
|
|
}
|
|
|
|
void dc_update_csi_detect(struct dc_dev *dev, struct surface *surface,
|
|
int mask_count, int ratio, bool enable, bool pll_mode)
|
|
{
|
|
unsigned long base = dev->base;
|
|
int value;
|
|
int count = 0;
|
|
|
|
dc_gpipe_reset(dev);
|
|
dc_update_layer(dev, surface);
|
|
dc_csi_mask_ratio_set(dev, mask_count, ratio);
|
|
dc_csi_timing_dectet_enable(dev, enable);
|
|
dc_triggle(dev);
|
|
set_tcon_ctrl_en(dev);
|
|
|
|
dc_vsync_enable(dev, false);
|
|
|
|
while (1) {
|
|
value = disp_read(base, DC_RA024);
|
|
disp_write(base, DC_RA024, value);
|
|
if (value & DC_MASK29_RA02X) {
|
|
count++;
|
|
if ((count == 2) && (!pll_mode)) {
|
|
tcon_auto_adj_enable(dev, true);
|
|
}
|
|
|
|
if (count == 3) {
|
|
if (pll_mode) {
|
|
tcon_csi_delay_set2(dev);
|
|
} else {
|
|
tcon_csi_delay_set(dev);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((count == 4) && (pll_mode)) {
|
|
tcon_auto_adj_enable(dev, true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
dc_triggle(dev);
|
|
if (dev->app.work_mode == WORK_MODE_CSI_DC_HS) {
|
|
dc_hsdk_enable(dev, dev->app.mode, true);
|
|
dc_triggle(dev);
|
|
}
|
|
dc_vsync_enable(dev, true);
|
|
}
|
|
|
|
void dc_set_bg_color(struct dc_dev *dev, int color)
|
|
{
|
|
unsigned long base = dev->base;
|
|
|
|
disp_write(base, DC_RE230, color);
|
|
}
|
|
|
|
struct dc_operations dc_ops = {
|
|
.init = dc_init,
|
|
.reset = dc_reset,
|
|
.update = dc_update,
|
|
.update_layer = dc_update_layer,
|
|
.triggle = dc_triggle,
|
|
.check_triggle_status = dc_check_triggle_status,
|
|
.vsync_enable = dc_vsync_enable,
|
|
.enable = set_tcon_ctrl_en,
|
|
.irq_handler = dc_irq_handler,
|
|
.hsdk_enable = dc_hsdk_enable,
|
|
.csi_mask_ratio_set = dc_csi_mask_ratio_set,
|
|
.csi_timing_dectet_enable = dc_csi_timing_dectet_enable,
|
|
.set_tcon_after_detect = dc_set_tcon_after_detect,
|
|
.tcon_auto_adj_enable = tcon_auto_adj_enable,
|
|
.tcon_csi_delay_set = tcon_csi_delay_set,
|
|
.update_csi_detect = dc_update_csi_detect,
|
|
.set_bg_color = dc_set_bg_color,
|
|
.clear_layers = dc_clear_layers,
|
|
};
|