Drivers/DRM: support display function for hikey970.

Add HDMI & LCD driver code use DRM/KMS subsystem for hikey970.

Signed-off-by: cailiwei@hisilicon.com
Signed-off-by: zhangxiubin1@huawei.com
This commit is contained in:
zwx342317
2018-02-08 10:45:53 +08:00
committed by Guodong Xu
parent 4c2a034fd7
commit 3db63453bc
22 changed files with 11524 additions and 152 deletions
@@ -37,3 +37,16 @@ config DRM_PANEL_HIKEY960_NTE300NTS
help
Say Y here if you want to enable LCD panel driver for Hikey960 boadr.
Current support panel: NTE300NTS(1920X1200)
config HISI_FB_970
tristate "DRM Support for Hisilicon Kirin970 series SoCs Platform"
depends on DRM && OF && ARM64
depends on DRM_MIPI_DSI
help
Choose this option if you have a hisilicon Kirin chipsets(kirin970).
If M is selected the module will be called kirin-drm.
config HDMI_ADV7511_AUDIO
tristate "HDMI Support ADV7511 audio"
help
Choose this option to support HDMI ADV7511 audio.
@@ -7,6 +7,10 @@ kirin-drm-y := kirin_fbdev.o \
kirin_drm_dss.o \
kirin_drm_dpe_utils.o \
kirin_drm_overlay_utils.o \
kirin_pwm.o \
hdmi/adv7535.o \
obj-$(CONFIG_HDMI_ADV7511_AUDIO) += hdmi/adv7535_audio.o
obj-$(CONFIG_DRM_KIRIN_960) += kirin-drm.o
obj-$(CONFIG_HISI_KIRIN_DW_DSI) += dw_drm_dsi.o
+445 -9
View File
@@ -30,10 +30,19 @@
#include <drm/drm_panel.h>
#include "dw_dsi_reg.h"
#if defined (CONFIG_HISI_FB_970)
#include "kirin970_dpe_reg.h"
#else
#include "kirin_dpe_reg.h"
#endif
#include "kirin_drm_dpe_utils.h"
#include "kirin_drm_drv.h"
#if defined (CONFIG_HISI_FB_970)
#define DTS_COMP_DSI_NAME "hisilicon,kirin970-dsi"
#else
#define DTS_COMP_DSI_NAME "hisilicon,hi3660-dsi"
#endif
#define ROUND(x, y) ((x) / (y) + \
((x) % (y) * 10 / (y) >= 5 ? 1 : 0))
@@ -110,11 +119,26 @@ struct mipi_phy_params {
u32 rg_pll_refsel; /*0x16[1:0]*/
u32 rg_pll_cp; /*0x16[7:5]*/
u32 load_command;
// for CDPHY
uint32_t rg_cphy_div; //Q
uint32_t rg_div; //M 0x4A[7:0]
uint32_t rg_pre_div; //N 0x49[0]
uint32_t rg_320m; //0x48[2]
uint32_t rg_2p5g; //0x48[1]
uint32_t rg_0p8v; //0x48[0]
uint32_t rg_lpf_r; //0x46[5:4]
uint32_t rg_cp; //0x46[3:0]
uint32_t t_prepare;
uint32_t t_lpx;
uint32_t t_prebegin;
uint32_t t_post;
};
struct dsi_hw_ctx {
void __iomem *base;
char __iomem *peri_crg_base;
void __iomem *pctrl_base;
struct clk *dss_dphy0_ref_clk;
struct clk *dss_dphy1_ref_clk;
@@ -171,6 +195,9 @@ struct mipi_panel_info {
/*only for Chicago<3660> use*/
u32 rg_vrefsel_vcm_clk_adjust;
u32 rg_vrefsel_vcm_data_adjust;
u32 phy_mode; //0: DPHY, 1:CPHY
u32 lp11_flag;
};
struct ldi_panel_info {
@@ -285,6 +312,263 @@ void dsi_set_output_client(struct drm_device *dev)
}
EXPORT_SYMBOL(dsi_set_output_client);
static void get_dsi_dphy_ctrl(struct dw_dsi *dsi,
struct mipi_phy_params *phy_ctrl)
{
struct mipi_panel_info *mipi = NULL;
struct drm_display_mode *mode = NULL;
u32 dphy_req_kHz;
int bpp;
u32 id = 0;
u32 ui = 0;
u32 m_pll = 0;
u32 n_pll = 0;
u64 lane_clock = 0;
u64 vco_div = 1;
u32 m_n_fract = 0;
u32 m_n_int = 0;
u32 accuracy = 0;
u32 unit_tx_byte_clk_hs = 0;
u32 clk_post = 0;
u32 clk_pre = 0;
u32 clk_t_hs_exit = 0;
u32 clk_pre_delay = 0;
u32 clk_t_hs_prepare = 0;
u32 clk_t_lpx = 0;
u32 clk_t_hs_zero = 0;
u32 clk_t_hs_trial = 0;
u32 data_post_delay = 0;
u32 data_t_hs_prepare = 0;
u32 data_t_hs_zero = 0;
u32 data_t_hs_trial = 0;
u32 data_t_lpx = 0;
WARN_ON(!phy_ctrl);
WARN_ON(!dsi);
id = dsi->cur_client;
mode = &dsi->cur_mode;
mipi = &dsi->mipi;
/*
* count phy params
*/
bpp = mipi_dsi_pixel_format_to_bpp(dsi->client[id].format);
if (bpp < 0)
return;
if (mode->clock > 80000)
dsi->client[id].lanes = 4;
else
dsi->client[id].lanes = 3;
if (dsi->client[id].phy_clock)
dphy_req_kHz = dsi->client[id].phy_clock;
else
dphy_req_kHz = mode->clock * bpp / dsi->client[id].lanes;
lane_clock = dphy_req_kHz / 1000;
DRM_INFO("Expected : lane_clock = %llu M\n", lane_clock);
/************************ PLL parameters config *********************/
//chip spec :
//If the output data rate is below 320 Mbps, RG_BNAD_SEL should be set to 1.
//At this mode a post divider of 1/4 will be applied to VCO.
if ((320 <= lane_clock) && (lane_clock <= 2500)) {
phy_ctrl->rg_band_sel = 0;
vco_div = 1;
} else if ((80 <= lane_clock) && (lane_clock < 320)) {
phy_ctrl->rg_band_sel = 1;
vco_div = 4;
} else {
DRM_ERROR("80M <= lane_clock< = 2500M, not support lane_clock = %llu M.\n", lane_clock);
}
m_n_int = lane_clock * vco_div * 1000000UL / DEFAULT_MIPI_CLK_RATE;
m_n_fract = ((lane_clock * vco_div * 1000000UL * 1000UL / DEFAULT_MIPI_CLK_RATE) % 1000) * 10 / 1000;
if (m_n_int % 2 == 0) {
if (m_n_fract * 6 >= 50) {
n_pll = 2;
m_pll = (m_n_int + 1) * n_pll;
} else if (m_n_fract * 6 >= 30) {
n_pll = 3;
m_pll = m_n_int * n_pll + 2;
} else {
n_pll = 1;
m_pll = m_n_int * n_pll;
}
} else {
if (m_n_fract * 6 >= 50) {
n_pll = 1;
m_pll = (m_n_int + 1) * n_pll;
} else if (m_n_fract * 6 >= 30) {
n_pll = 1;
m_pll = (m_n_int + 1) * n_pll;
} else if (m_n_fract * 6 >= 10) {
n_pll = 3;
m_pll = m_n_int * n_pll + 1;
} else {
n_pll = 2;
m_pll = m_n_int * n_pll;
}
}
//n_pll = 2;
m_pll = (u32)(lane_clock * vco_div * n_pll * 1000000UL / DEFAULT_MIPI_CLK_RATE);
lane_clock = m_pll * (DEFAULT_MIPI_CLK_RATE / n_pll) / vco_div;
if (lane_clock > 750000000) {
phy_ctrl->rg_cp = 3;
} else if ((80000000 <= lane_clock) && (lane_clock <= 750000000)) {
phy_ctrl->rg_cp = 1;
} else {
DRM_ERROR("80M <= lane_clock< = 2500M, not support lane_clock = %llu M.\n", lane_clock);
}
//chip spec :
phy_ctrl->rg_pre_div = n_pll - 1;
phy_ctrl->rg_div = m_pll;
phy_ctrl->rg_0p8v = 0;
phy_ctrl->rg_2p5g = 1;
phy_ctrl->rg_320m = 0;
phy_ctrl->rg_lpf_r = 0;
//TO DO HSTX select VCM VREF
phy_ctrl->rg_vrefsel_vcm = 0x5d;
/******************** clock/data lane parameters config ******************/
accuracy = 10;
ui = (u32)(10 * 1000000000UL * accuracy / lane_clock);
//unit of measurement
unit_tx_byte_clk_hs = 8 * ui;
// D-PHY Specification : 60ns + 52*UI <= clk_post
clk_post = 600 * accuracy + 52 * ui + unit_tx_byte_clk_hs + mipi->clk_post_adjust * ui;
// D-PHY Specification : clk_pre >= 8*UI
clk_pre = 8 * ui + unit_tx_byte_clk_hs + mipi->clk_pre_adjust * ui;
// D-PHY Specification : clk_t_hs_exit >= 100ns
clk_t_hs_exit = 1000 * accuracy + 100 * accuracy + mipi->clk_t_hs_exit_adjust * ui;
// clocked by TXBYTECLKHS
clk_pre_delay = 0 + mipi->clk_pre_delay_adjust * ui;
// D-PHY Specification : clk_t_hs_trial >= 60ns
// clocked by TXBYTECLKHS
clk_t_hs_trial = 600 * accuracy + 3 * unit_tx_byte_clk_hs + mipi->clk_t_hs_trial_adjust * ui;
// D-PHY Specification : 38ns <= clk_t_hs_prepare <= 95ns
// clocked by TXBYTECLKHS
clk_t_hs_prepare = 660 * accuracy;
// clocked by TXBYTECLKHS
data_post_delay = 0 + mipi->data_post_delay_adjust * ui;
// D-PHY Specification : data_t_hs_trial >= max( n*8*UI, 60ns + n*4*UI ), n = 1
// clocked by TXBYTECLKHS
data_t_hs_trial = ((600 * accuracy + 4 * ui) >= (8 * ui) ? (600 * accuracy + 4 * ui) : (8 * ui)) +
2 * unit_tx_byte_clk_hs + mipi->data_t_hs_trial_adjust * ui;
// D-PHY Specification : 40ns + 4*UI <= data_t_hs_prepare <= 85ns + 6*UI
// clocked by TXBYTECLKHS
data_t_hs_prepare = 400 * accuracy + 4*ui;
// D-PHY chip spec : clk_t_lpx + clk_t_hs_prepare > 200ns
// D-PHY Specification : clk_t_lpx >= 50ns
// clocked by TXBYTECLKHS
clk_t_lpx = (uint32_t)(2000 * accuracy + 10 * accuracy + mipi->clk_t_lpx_adjust * ui - clk_t_hs_prepare);
// D-PHY Specification : clk_t_hs_zero + clk_t_hs_prepare >= 300 ns
// clocked by TXBYTECLKHS
clk_t_hs_zero = (uint32_t)(3000 * accuracy + 3 * unit_tx_byte_clk_hs + mipi->clk_t_hs_zero_adjust * ui - clk_t_hs_prepare);
// D-PHY chip spec : data_t_lpx + data_t_hs_prepare > 200ns
// D-PHY Specification : data_t_lpx >= 50ns
// clocked by TXBYTECLKHS
data_t_lpx = (uint32_t)(2000 * accuracy + 10 * accuracy + mipi->data_t_lpx_adjust * ui - data_t_hs_prepare);
// D-PHY Specification : data_t_hs_zero + data_t_hs_prepare >= 145ns + 10*UI
// clocked by TXBYTECLKHS
data_t_hs_zero = (uint32_t)(1450 * accuracy + 10 * ui +
3 * unit_tx_byte_clk_hs + mipi->data_t_hs_zero_adjust * ui - data_t_hs_prepare);
phy_ctrl->clk_pre_delay = ROUND1(clk_pre_delay, unit_tx_byte_clk_hs);
phy_ctrl->clk_t_hs_prepare = ROUND1(clk_t_hs_prepare, unit_tx_byte_clk_hs);
phy_ctrl->clk_t_lpx = ROUND1(clk_t_lpx, unit_tx_byte_clk_hs);
phy_ctrl->clk_t_hs_zero = ROUND1(clk_t_hs_zero, unit_tx_byte_clk_hs);
phy_ctrl->clk_t_hs_trial = ROUND1(clk_t_hs_trial, unit_tx_byte_clk_hs);
phy_ctrl->data_post_delay = ROUND1(data_post_delay, unit_tx_byte_clk_hs);
phy_ctrl->data_t_hs_prepare = ROUND1(data_t_hs_prepare, unit_tx_byte_clk_hs);
phy_ctrl->data_t_lpx = ROUND1(data_t_lpx, unit_tx_byte_clk_hs);
phy_ctrl->data_t_hs_zero = ROUND1(data_t_hs_zero, unit_tx_byte_clk_hs);
phy_ctrl->data_t_hs_trial = ROUND1(data_t_hs_trial, unit_tx_byte_clk_hs);
phy_ctrl->clk_post_delay = phy_ctrl->data_t_hs_trial + ROUND1(clk_post, unit_tx_byte_clk_hs);
phy_ctrl->data_pre_delay = phy_ctrl->clk_pre_delay + 2 + phy_ctrl->clk_t_lpx +
phy_ctrl->clk_t_hs_prepare + phy_ctrl->clk_t_hs_zero + 8 + ROUND1(clk_pre, unit_tx_byte_clk_hs) ;
phy_ctrl->clk_lane_lp2hs_time = phy_ctrl->clk_pre_delay + phy_ctrl->clk_t_lpx + phy_ctrl->clk_t_hs_prepare +
phy_ctrl->clk_t_hs_zero + 5 + 7;
phy_ctrl->clk_lane_hs2lp_time = phy_ctrl->clk_t_hs_trial + phy_ctrl->clk_post_delay + 8 + 4;
phy_ctrl->data_lane_lp2hs_time = phy_ctrl->data_pre_delay + phy_ctrl->data_t_lpx + phy_ctrl->data_t_hs_prepare +
phy_ctrl->data_t_hs_zero + 5 + 7;
phy_ctrl->data_lane_hs2lp_time = phy_ctrl->data_t_hs_trial + 8 + 5;
phy_ctrl->phy_stop_wait_time = phy_ctrl->clk_post_delay + 4 + phy_ctrl->clk_t_hs_trial +
ROUND1(clk_t_hs_exit, unit_tx_byte_clk_hs) - (phy_ctrl->data_post_delay + 4 + phy_ctrl->data_t_hs_trial) + 3;
phy_ctrl->lane_byte_clk = lane_clock / 8;
phy_ctrl->clk_division = (((phy_ctrl->lane_byte_clk / 2) % mipi->max_tx_esc_clk) > 0) ?
(uint32_t)(phy_ctrl->lane_byte_clk / 2 / mipi->max_tx_esc_clk + 1) :
(uint32_t)(phy_ctrl->lane_byte_clk / 2 / mipi->max_tx_esc_clk);
DRM_DEBUG("DPHY clock_lane and data_lane config : \n"
"lane_clock = %llu, n_pll=%d, m_pll=%d\n"
"rg_cp=%d\n"
"rg_band_sel=%d\n"
"rg_vrefsel_vcm=%d\n"
"clk_pre_delay=%d\n"
"clk_post_delay=%d\n"
"clk_t_hs_prepare=%d\n"
"clk_t_lpx=%d\n"
"clk_t_hs_zero=%d\n"
"clk_t_hs_trial=%d\n"
"data_pre_delay=%d\n"
"data_post_delay=%d\n"
"data_t_hs_prepare=%d\n"
"data_t_lpx=%d\n"
"data_t_hs_zero=%d\n"
"data_t_hs_trial=%d\n"
"clk_lane_lp2hs_time=%d\n"
"clk_lane_hs2lp_time=%d\n"
"data_lane_lp2hs_time=%d\n"
"data_lane_hs2lp_time=%d\n"
"phy_stop_wait_time=%d\n",
lane_clock, n_pll, m_pll,
phy_ctrl->rg_cp,
phy_ctrl->rg_band_sel,
phy_ctrl->rg_vrefsel_vcm,
phy_ctrl->clk_pre_delay,
phy_ctrl->clk_post_delay,
phy_ctrl->clk_t_hs_prepare,
phy_ctrl->clk_t_lpx,
phy_ctrl->clk_t_hs_zero,
phy_ctrl->clk_t_hs_trial,
phy_ctrl->data_pre_delay,
phy_ctrl->data_post_delay,
phy_ctrl->data_t_hs_prepare,
phy_ctrl->data_t_lpx,
phy_ctrl->data_t_hs_zero,
phy_ctrl->data_t_hs_trial,
phy_ctrl->clk_lane_lp2hs_time,
phy_ctrl->clk_lane_hs2lp_time,
phy_ctrl->data_lane_lp2hs_time,
phy_ctrl->data_lane_hs2lp_time,
phy_ctrl->phy_stop_wait_time);
}
static void get_dsi_phy_ctrl(struct dw_dsi *dsi,
struct mipi_phy_params *phy_ctrl)
{
@@ -572,7 +856,7 @@ static void get_dsi_phy_ctrl(struct dw_dsi *dsi,
(phy_ctrl->lane_byte_clk / 2 / mipi->max_tx_esc_clk + 1) :
(phy_ctrl->lane_byte_clk / 2 / mipi->max_tx_esc_clk);
DRM_INFO("PHY clock_lane and data_lane config : \n"
DRM_DEBUG("PHY clock_lane and data_lane config : \n"
"rg_vrefsel_vcm=%u\n"
"clk_pre_delay=%u\n"
"clk_post_delay=%u\n"
@@ -644,6 +928,7 @@ static void dsi_set_burst_mode(void __iomem *base, unsigned long flags)
else
val = DSI_BURST_SYNC_PULSES_1;
DRM_INFO("burst_mode = 0x%x (DSI_NON_BURST_SYNC_PULSES => 0)", val);
set_reg(base + MIPIDSI_VID_MODE_CFG_OFFSET, val, 2, 0);
}
@@ -669,6 +954,85 @@ static void dsi_phy_tst_set(void __iomem *base, u32 reg, u32 val)
writel(0x00, base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
}
static void mipi_config_dphy_spec1v2_parameter(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
{
uint32_t i;
uint32_t addr = 0;
u32 lanes;
lanes = dsi->client[dsi->cur_client].lanes - 1;
#if defined (CONFIG_HISI_FB_970)
for (i = 0; i <= lanes; i++) {
//Lane Transmission Property
addr = MIPIDSI_PHY_TST_LANE_TRANSMISSION_PROPERTY + (i << 5);
dsi_phy_tst_set(mipi_dsi_base, addr, 0x43);
}
#endif
//pre_delay of clock lane request setting
dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_PRE_DELAY, DSS_REDUCE(dsi->phy.clk_pre_delay));
//post_delay of clock lane request setting
dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_POST_DELAY, DSS_REDUCE(dsi->phy.clk_post_delay));
//clock lane timing ctrl - t_lpx
dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_TLPX, DSS_REDUCE(dsi->phy.clk_t_lpx));
//clock lane timing ctrl - t_hs_prepare
dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_PREPARE, DSS_REDUCE(dsi->phy.clk_t_hs_prepare));
//clock lane timing ctrl - t_hs_zero
dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_ZERO, DSS_REDUCE(dsi->phy.clk_t_hs_zero));
//clock lane timing ctrl - t_hs_trial
dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_TRAIL, DSS_REDUCE(dsi->phy.clk_t_hs_trial));
for (i = 0; i <= (lanes + 1); i++) {//lint !e850
if (i == 2) {
i++; //addr: lane0:0x60; lane1:0x80; lane2:0xC0; lane3:0xE0
}
//data lane pre_delay
addr = MIPIDSI_PHY_TST_DATA_PRE_DELAY + (i << 5);
dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_pre_delay));
//data lane post_delay
addr = MIPIDSI_PHY_TST_DATA_POST_DELAY + (i << 5);
dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_post_delay));
//data lane timing ctrl - t_lpx
addr = MIPIDSI_PHY_TST_DATA_TLPX + (i << 5);
dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_t_lpx));
//data lane timing ctrl - t_hs_prepare
addr = MIPIDSI_PHY_TST_DATA_PREPARE + (i << 5);
dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_t_hs_prepare));
//data lane timing ctrl - t_hs_zero
addr = MIPIDSI_PHY_TST_DATA_ZERO + (i << 5);
dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_t_hs_zero));
//data lane timing ctrl - t_hs_trial
addr = MIPIDSI_PHY_TST_DATA_TRAIL + (i << 5);
dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_t_hs_trial));
DRM_DEBUG("DPHY spec1v2 config : \n"
"addr=0x%x\n"
"clk_pre_delay=%u\n"
"clk_t_hs_trial=%u\n"
"data_t_hs_zero=%u\n"
"data_t_lpx=%u\n"
"data_t_hs_prepare=%u\n",
addr,
dsi->phy.clk_pre_delay,
dsi->phy.clk_t_hs_trial,
dsi->phy.data_t_hs_zero,
dsi->phy.data_t_lpx,
dsi->phy.data_t_hs_prepare);
}
}
static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
{
u32 hline_time = 0;
@@ -697,7 +1061,12 @@ static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
}
memset(&dsi->phy, 0, sizeof(struct mipi_phy_params));
#if defined (CONFIG_HISI_FB_970)
get_dsi_dphy_ctrl(dsi, &dsi->phy);
#else
get_dsi_phy_ctrl(dsi, &dsi->phy);
#endif
rect.x = 0;
rect.y = 0;
@@ -716,6 +1085,36 @@ static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000001);
outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
#if defined (CONFIG_HISI_FB_970)
dsi_phy_tst_set(mipi_dsi_base, 0x0042, 0x21);
//PLL configuration I
dsi_phy_tst_set(mipi_dsi_base, 0x0046, dsi->phy.rg_cp + (dsi->phy.rg_lpf_r << 4));
//PLL configuration II
dsi_phy_tst_set(mipi_dsi_base, 0x0048, dsi->phy.rg_0p8v + (dsi->phy.rg_2p5g << 1) +
(dsi->phy.rg_320m << 2) + (dsi->phy.rg_band_sel << 3));
//PLL configuration III
dsi_phy_tst_set(mipi_dsi_base, 0x0049, dsi->phy.rg_pre_div);
//PLL configuration IV
dsi_phy_tst_set(mipi_dsi_base, 0x004A, dsi->phy.rg_div);
dsi_phy_tst_set(mipi_dsi_base, 0x004F, 0xf0);
dsi_phy_tst_set(mipi_dsi_base, 0x0050, 0xc0);
dsi_phy_tst_set(mipi_dsi_base, 0x0051, 0x22);
dsi_phy_tst_set(mipi_dsi_base, 0x0053, dsi->phy.rg_vrefsel_vcm);
/*enable BTA*/
dsi_phy_tst_set(mipi_dsi_base, 0x0054, 0x03);
//PLL update control
dsi_phy_tst_set(mipi_dsi_base, 0x004B, 0x1);
//set dphy spec parameter
mipi_config_dphy_spec1v2_parameter(dsi, mipi_dsi_base);
#else
/* physical configuration PLL I*/
dsi_phy_tst_set(mipi_dsi_base, 0x14,
(dsi->phy.rg_pll_fbd_s << 4) + (dsi->phy.rg_pll_enswc << 3) +
@@ -794,6 +1193,7 @@ static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
tmp = 0x37 + (i << 4);
dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_ta_get));
}
#endif
outp32(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x00000007);
@@ -924,6 +1324,13 @@ static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_CFG_OFFSET, dsi->phy.data_lane_lp2hs_time, 10, 0);
set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_CFG_OFFSET, dsi->phy.data_lane_hs2lp_time, 10, 16);
#if defined (CONFIG_HISI_FB_970)
//16~19bit:pclk_en, pclk_sel, dpipclk_en, dpipclk_sel
set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, 0x5, 4, 16);
//0:dphy
set_reg(mipi_dsi_base + PHY_MODE, 0x0, 1, 0);
#endif
/* Waking up Core*/
set_reg(mipi_dsi_base + MIPIDSI_PWR_UP_OFFSET, 0x1, 1, 0);
}
@@ -962,7 +1369,12 @@ static int mipi_dsi_on_sub1(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
/* mipi init */
dsi_mipi_init(dsi, mipi_dsi_base);
DRM_INFO("dsi_mipi_init ok\n");
/* dsi memory init */
#if defined (CONFIG_HISI_FB_970)
outp32(mipi_dsi_base + DSI_MEM_CTRL, 0x02600008);
#endif
/* switch to cmd mode */
set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x1, 1, 0);
/* cmd mode: low power mode */
@@ -979,6 +1391,7 @@ static int mipi_dsi_on_sub1(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
static int mipi_dsi_on_sub2(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
{
WARN_ON(!mipi_dsi_base);
u64 pctrl_dphytx_stopcnt = 0;
/* switch to video mode */
set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x0, 1, 0);
@@ -989,6 +1402,17 @@ static int mipi_dsi_on_sub2(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
/* enable generate High Speed clock, continue clock */
set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x1, 2, 0);
#if defined(CONFIG_HISI_FB_970)
// init: wait DPHY 4 data lane stopstate
pctrl_dphytx_stopcnt = (u64)(dsi->ldi.h_back_porch +
dsi->ldi.h_front_porch + dsi->ldi.h_pulse_width + dsi->cur_mode.hdisplay + 5) *
DEFAULT_PCLK_PCTRL_RATE / (dsi->cur_mode.clock * 1000);
DRM_DEBUG("pctrl_dphytx_stopcnt = %llu\n", pctrl_dphytx_stopcnt);
//FIXME:
outp32(dsi->ctx->pctrl_base + PERI_CTRL29, (u32)pctrl_dphytx_stopcnt);
#endif
return 0;
}
@@ -1504,29 +1928,40 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
np = of_find_compatible_node(NULL, NULL, DTS_COMP_DSI_NAME);
if (!np) {
DRM_ERROR("NOT FOUND device node %s!\n",
DTS_COMP_DSI_NAME);
return -ENXIO;
DRM_ERROR("NOT FOUND device node %s!\n",
DTS_COMP_DSI_NAME);
return -ENXIO;
}
ctx->base = of_iomap(np, 0);
if (!(ctx->base)) {
DRM_ERROR ("failed to get base resource.\n");
return -ENXIO;
DRM_ERROR ("failed to get dsi base resource.\n");
return -ENXIO;
}
DRM_INFO("dsi base =0x%x.\n", ctx->base);
ctx->peri_crg_base = of_iomap(np, 1);
if (!(ctx->peri_crg_base)) {
DRM_ERROR ("failed to get peri_crg_base resource.\n");
return -ENXIO;
DRM_ERROR ("failed to get peri_crg_base resource.\n");
return -ENXIO;
}
#if defined (CONFIG_HISI_FB_970)
ctx->pctrl_base = of_iomap(np, 2);
if (!(ctx->pctrl_base)) {
DRM_ERROR ("failed to get dss pctrl_base resource.\n");
return -ENXIO;
}
#endif
dsi->gpio_mux = devm_gpiod_get(&pdev->dev, "mux", GPIOD_OUT_HIGH);
if (IS_ERR(dsi->gpio_mux))
return PTR_ERR(dsi->gpio_mux);
/* set dsi default output to panel */
dsi->cur_client = OUT_PANEL;
DRM_INFO("dsi cur_client is %d <0->hdmi;1->panel> \n", dsi->cur_client);
/*dis-reset*/
/*ip_reset_dis_dsi0, ip_reset_dis_dsi1*/
outp32(ctx->peri_crg_base + PERRSTDIS3, 0x30000000);
@@ -1630,6 +2065,7 @@ static int dsi_remove(struct platform_device *pdev)
static const struct of_device_id dsi_of_match[] = {
{.compatible = "hisilicon,hi3660-dsi"},
{.compatible = "hisilicon,kirin970-dsi"},
{ }
};
MODULE_DEVICE_TABLE(of, dsi_of_match);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,351 @@
/*
* Analog Devices ADV7511 HDMI transmitter driver
*
* Copyright 2012 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
#ifndef __DRM_I2C_ADV7511_H__
#define __DRM_I2C_ADV7511_H__
#include <linux/hdmi.h>
#include <drm/drm_crtc_helper.h>
struct regmap;
struct adv7511;
int adv7511_packet_enable(struct adv7511 *adv7511, unsigned int packet);
int adv7511_packet_disable(struct adv7511 *adv7511, unsigned int packet);
int adv7511_audio_init(struct device *dev);
void adv7511_audio_exit(struct device *dev);
#define ADV7511_REG_CHIP_REVISION 0x00
#define ADV7511_REG_N0 0x01
#define ADV7511_REG_N1 0x02
#define ADV7511_REG_N2 0x03
#define ADV7511_REG_SPDIF_FREQ 0x04
#define ADV7511_REG_CTS_AUTOMATIC1 0x05
#define ADV7511_REG_CTS_AUTOMATIC2 0x06
#define ADV7511_REG_CTS_MANUAL0 0x07
#define ADV7511_REG_CTS_MANUAL1 0x08
#define ADV7511_REG_CTS_MANUAL2 0x09
#define ADV7511_REG_AUDIO_SOURCE 0x0a
#define ADV7511_REG_AUDIO_CONFIG 0x0b
#define ADV7511_REG_I2S_CONFIG 0x0c
#define ADV7511_REG_I2S_WIDTH 0x0d
#define ADV7511_REG_AUDIO_SUB_SRC0 0x0e
#define ADV7511_REG_AUDIO_SUB_SRC1 0x0f
#define ADV7511_REG_AUDIO_SUB_SRC2 0x10
#define ADV7511_REG_AUDIO_SUB_SRC3 0x11
#define ADV7511_REG_AUDIO_CFG1 0x12
#define ADV7511_REG_AUDIO_CFG2 0x13
#define ADV7511_REG_AUDIO_CFG3 0x14
#define ADV7511_REG_I2C_FREQ_ID_CFG 0x15
#define ADV7511_REG_VIDEO_INPUT_CFG1 0x16
#define ADV7511_REG_CSC_UPPER(x) (0x18 + (x) * 2)
#define ADV7511_REG_CSC_LOWER(x) (0x19 + (x) * 2)
#define ADV7511_REG_SYNC_DECODER(x) (0x30 + (x))
#define ADV7511_REG_DE_GENERATOR (0x35 + (x))
#define ADV7511_REG_PIXEL_REPETITION 0x3b
#define ADV7511_REG_VIC_MANUAL 0x3c
#define ADV7511_REG_VIC_SEND 0x3d
#define ADV7511_REG_VIC_DETECTED 0x3e
#define ADV7511_REG_AUX_VIC_DETECTED 0x3f
#define ADV7511_REG_PACKET_ENABLE0 0x40
#define ADV7511_REG_POWER 0x41
#define ADV7511_REG_STATUS 0x42
#define ADV7511_REG_EDID_I2C_ADDR 0x43
#define ADV7511_REG_PACKET_ENABLE1 0x44
#define ADV7511_REG_PACKET_I2C_ADDR 0x45
#define ADV7511_REG_DSD_ENABLE 0x46
#define ADV7511_REG_VIDEO_INPUT_CFG2 0x48
#define ADV7511_REG_INFOFRAME_UPDATE 0x4a
#define ADV7511_REG_GC(x) (0x4b + (x)) /* 0x4b - 0x51 */
#define ADV7511_REG_AVI_INFOFRAME_VERSION 0x52
#define ADV7511_REG_AVI_INFOFRAME_LENGTH 0x53
#define ADV7511_REG_AVI_INFOFRAME_CHECKSUM 0x54
#define ADV7511_REG_AVI_INFOFRAME(x) (0x55 + (x)) /* 0x55 - 0x6f */
#define ADV7511_REG_AUDIO_INFOFRAME_VERSION 0x70
#define ADV7511_REG_AUDIO_INFOFRAME_LENGTH 0x71
#define ADV7511_REG_AUDIO_INFOFRAME_CHECKSUM 0x72
#define ADV7511_REG_AUDIO_INFOFRAME(x) (0x73 + (x)) /* 0x73 - 0x7c */
#define ADV7511_REG_INT_ENABLE(x) (0x94 + (x))
#define ADV7511_REG_INT(x) (0x96 + (x))
#define ADV7511_REG_INPUT_CLK_DIV 0x9d
#define ADV7511_REG_PLL_STATUS 0x9e
#define ADV7511_REG_HDMI_POWER 0xa1
#define ADV7511_REG_HDCP_HDMI_CFG 0xaf
#define ADV7511_REG_AN(x) (0xb0 + (x)) /* 0xb0 - 0xb7 */
#define ADV7511_REG_HDCP_STATUS 0xb8
#define ADV7511_REG_BCAPS 0xbe
#define ADV7511_REG_BKSV(x) (0xc0 + (x)) /* 0xc0 - 0xc3 */
#define ADV7511_REG_EDID_SEGMENT 0xc4
#define ADV7511_REG_DDC_STATUS 0xc8
#define ADV7511_REG_EDID_READ_CTRL 0xc9
#define ADV7511_REG_BSTATUS(x) (0xca + (x)) /* 0xca - 0xcb */
#define ADV7511_REG_TIMING_GEN_SEQ 0xd0
#define ADV7511_REG_POWER2 0xd6
#define ADV7511_REG_HSYNC_PLACEMENT_MSB 0xfa
#define ADV7511_REG_SYNC_ADJUSTMENT(x) (0xd7 + (x)) /* 0xd7 - 0xdc */
#define ADV7511_REG_TMDS_CLOCK_INV 0xde
#define ADV7511_REG_ARC_CTRL 0xdf
#define ADV7511_REG_CEC_I2C_ADDR 0xe1
#define ADV7511_REG_CEC_CTRL 0xe2
#define ADV7511_REG_CHIP_ID_HIGH 0xf5
#define ADV7511_REG_CHIP_ID_LOW 0xf6
#define ADV7511_CSC_ENABLE BIT(7)
#define ADV7511_CSC_UPDATE_MODE BIT(5)
#define ADV7511_INT0_HDP BIT(7)
#define ADV7511_INT0_VSYNC BIT(5)
#define ADV7511_INT0_AUDIO_FIFO_FULL BIT(4)
#define ADV7511_INT0_EDID_READY BIT(2)
#define ADV7511_INT0_HDCP_AUTHENTICATED BIT(1)
#define ADV7511_INT1_DDC_ERROR BIT(7)
#define ADV7511_INT1_BKSV BIT(6)
#define ADV7511_INT1_CEC_TX_READY BIT(5)
#define ADV7511_INT1_CEC_TX_ARBIT_LOST BIT(4)
#define ADV7511_INT1_CEC_TX_RETRY_TIMEOUT BIT(3)
#define ADV7511_INT1_CEC_RX_READY3 BIT(2)
#define ADV7511_INT1_CEC_RX_READY2 BIT(1)
#define ADV7511_INT1_CEC_RX_READY1 BIT(0)
#define ADV7511_ARC_CTRL_POWER_DOWN BIT(0)
#define ADV7511_CEC_CTRL_POWER_DOWN BIT(0)
#define ADV7511_POWER_POWER_DOWN BIT(6)
#define ADV7511_HDMI_CFG_MODE_MASK 0x2
#define ADV7511_HDMI_CFG_MODE_DVI 0x0
#define ADV7511_HDMI_CFG_MODE_HDMI 0x2
#define ADV7511_AUDIO_SELECT_I2C 0x0
#define ADV7511_AUDIO_SELECT_SPDIF 0x1
#define ADV7511_AUDIO_SELECT_DSD 0x2
#define ADV7511_AUDIO_SELECT_HBR 0x3
#define ADV7511_AUDIO_SELECT_DST 0x4
#define ADV7511_I2S_SAMPLE_LEN_16 0x2
#define ADV7511_I2S_SAMPLE_LEN_20 0x3
#define ADV7511_I2S_SAMPLE_LEN_18 0x4
#define ADV7511_I2S_SAMPLE_LEN_22 0x5
#define ADV7511_I2S_SAMPLE_LEN_19 0x8
#define ADV7511_I2S_SAMPLE_LEN_23 0x9
#define ADV7511_I2S_SAMPLE_LEN_24 0xb
#define ADV7511_I2S_SAMPLE_LEN_17 0xc
#define ADV7511_I2S_SAMPLE_LEN_21 0xd
#define ADV7511_SAMPLE_FREQ_44100 0x0
#define ADV7511_SAMPLE_FREQ_48000 0x2
#define ADV7511_SAMPLE_FREQ_32000 0x3
#define ADV7511_SAMPLE_FREQ_88200 0x8
#define ADV7511_SAMPLE_FREQ_96000 0xa
#define ADV7511_SAMPLE_FREQ_176400 0xc
#define ADV7511_SAMPLE_FREQ_192000 0xe
#define ADV7511_STATUS_POWER_DOWN_POLARITY BIT(7)
#define ADV7511_STATUS_HPD BIT(6)
#define ADV7511_STATUS_MONITOR_SENSE BIT(5)
#define ADV7511_STATUS_I2S_32BIT_MODE BIT(3)
#define ADV7511_PACKET_ENABLE_N_CTS BIT(8+6)
#define ADV7511_PACKET_ENABLE_AUDIO_SAMPLE BIT(8+5)
#define ADV7511_PACKET_ENABLE_AVI_INFOFRAME BIT(8+4)
#define ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME BIT(8+3)
#define ADV7511_PACKET_ENABLE_GC BIT(7)
#define ADV7511_PACKET_ENABLE_SPD BIT(6)
#define ADV7511_PACKET_ENABLE_MPEG BIT(5)
#define ADV7511_PACKET_ENABLE_ACP BIT(4)
#define ADV7511_PACKET_ENABLE_ISRC BIT(3)
#define ADV7511_PACKET_ENABLE_GM BIT(2)
#define ADV7511_PACKET_ENABLE_SPARE2 BIT(1)
#define ADV7511_PACKET_ENABLE_SPARE1 BIT(0)
#define ADV7511_REG_POWER2_HDP_SRC_MASK 0xc0
#define ADV7511_REG_POWER2_HDP_SRC_BOTH 0x00
#define ADV7511_REG_POWER2_HDP_SRC_HDP 0x40
#define ADV7511_REG_POWER2_HDP_SRC_CEC 0x80
#define ADV7511_REG_POWER2_HDP_SRC_NONE 0xc0
#define ADV7511_REG_POWER2_TDMS_ENABLE BIT(4)
#define ADV7511_REG_POWER2_GATE_INPUT_CLK BIT(0)
#define ADV7511_LOW_REFRESH_RATE_NONE 0x0
#define ADV7511_LOW_REFRESH_RATE_24HZ 0x1
#define ADV7511_LOW_REFRESH_RATE_25HZ 0x2
#define ADV7511_LOW_REFRESH_RATE_30HZ 0x3
#define ADV7511_AUDIO_CFG3_LEN_MASK 0x0f
#define ADV7511_I2C_FREQ_ID_CFG_RATE_MASK 0xf0
#define ADV7511_AUDIO_SOURCE_I2S 0
#define ADV7511_AUDIO_SOURCE_SPDIF 1
#define ADV7511_I2S_FORMAT_I2S 0
#define ADV7511_I2S_FORMAT_RIGHT_J 1
#define ADV7511_I2S_FORMAT_LEFT_J 2
#define ADV7511_PACKET(p, x) ((p) * 0x20 + (x))
#define ADV7511_PACKET_SDP(x) ADV7511_PACKET(0, x)
#define ADV7511_PACKET_MPEG(x) ADV7511_PACKET(1, x)
#define ADV7511_PACKET_ACP(x) ADV7511_PACKET(2, x)
#define ADV7511_PACKET_ISRC1(x) ADV7511_PACKET(3, x)
#define ADV7511_PACKET_ISRC2(x) ADV7511_PACKET(4, x)
#define ADV7511_PACKET_GM(x) ADV7511_PACKET(5, x)
#define ADV7511_PACKET_SPARE(x) ADV7511_PACKET(6, x)
enum adv7511_input_clock {
ADV7511_INPUT_CLOCK_1X,
ADV7511_INPUT_CLOCK_2X,
ADV7511_INPUT_CLOCK_DDR,
};
enum adv7511_input_justification {
ADV7511_INPUT_JUSTIFICATION_EVENLY = 0,
ADV7511_INPUT_JUSTIFICATION_RIGHT = 1,
ADV7511_INPUT_JUSTIFICATION_LEFT = 2,
};
enum adv7511_input_sync_pulse {
ADV7511_INPUT_SYNC_PULSE_DE = 0,
ADV7511_INPUT_SYNC_PULSE_HSYNC = 1,
ADV7511_INPUT_SYNC_PULSE_VSYNC = 2,
ADV7511_INPUT_SYNC_PULSE_NONE = 3,
};
/**
* enum adv7511_sync_polarity - Polarity for the input sync signals
* @ADV7511_SYNC_POLARITY_PASSTHROUGH: Sync polarity matches that of
* the currently configured mode.
* @ADV7511_SYNC_POLARITY_LOW: Sync polarity is low
* @ADV7511_SYNC_POLARITY_HIGH: Sync polarity is high
*
* If the polarity is set to either LOW or HIGH the driver will configure the
* ADV7511 to internally invert the sync signal if required to match the sync
* polarity setting for the currently selected output mode.
*
* If the polarity is set to PASSTHROUGH, the ADV7511 will route the signal
* unchanged. This is used when the upstream graphics core already generates
* the sync signals with the correct polarity.
*/
enum adv7511_sync_polarity {
ADV7511_SYNC_POLARITY_PASSTHROUGH,
ADV7511_SYNC_POLARITY_LOW,
ADV7511_SYNC_POLARITY_HIGH,
};
enum adv7511_type {
ADV7511,
ADV7533,
};
struct adv7511 {
struct i2c_client *i2c_main;
struct i2c_client *i2c_edid;
struct i2c_client *i2c_cec;
struct i2c_client *i2c_packet;
struct regmap *regmap;
struct regmap *regmap_cec;
struct regmap *regmap_packet;
enum drm_connector_status status;
bool powered;
struct regulator *vdd;
struct regulator *v1p2;
struct drm_display_mode curr_mode;
unsigned int f_tmds;
unsigned int f_audio;
unsigned int audio_source;
unsigned int current_edid_segment;
uint8_t edid_buf[256];
bool edid_read;
wait_queue_head_t wq;
struct drm_encoder *encoder;
struct drm_connector connector;
struct drm_bridge bridge;
bool embedded_sync;
enum adv7511_sync_polarity vsync_polarity;
enum adv7511_sync_polarity hsync_polarity;
bool rgb;
struct edid *edid;
struct gpio_desc *gpio_pd;
/* ADV7533 DSI RX related params */
struct device_node *host_node;
struct mipi_dsi_device *dsi;
u8 num_dsi_lanes;
enum adv7511_type type;
};
/**
* struct adv7511_link_config - Describes adv7511 hardware configuration
* @input_color_depth: Number of bits per color component (8, 10 or 12)
* @input_colorspace: The input colorspace (RGB, YUV444, YUV422)
* @input_clock: The input video clock style (1x, 2x, DDR)
* @input_style: The input component arrangement variant
* @input_justification: Video input format bit justification
* @clock_delay: Clock delay for the input clock (in ps)
* @embedded_sync: Video input uses BT.656-style embedded sync
* @sync_pulse: Select the sync pulse
* @vsync_polarity: vsync input signal configuration
* @hsync_polarity: hsync input signal configuration
*/
struct adv7511_link_config {
unsigned int input_color_depth;
enum hdmi_colorspace input_colorspace;
enum adv7511_input_clock input_clock;
unsigned int input_style;
enum adv7511_input_justification input_justification;
int clock_delay;
bool embedded_sync;
enum adv7511_input_sync_pulse sync_pulse;
enum adv7511_sync_polarity vsync_polarity;
enum adv7511_sync_polarity hsync_polarity;
};
/**
* enum adv7511_csc_scaling - Scaling factor for the ADV7511 CSC
* @ADV7511_CSC_SCALING_1: CSC results are not scaled
* @ADV7511_CSC_SCALING_2: CSC results are scaled by a factor of two
* @ADV7511_CSC_SCALING_4: CSC results are scalled by a factor of four
*/
enum adv7511_csc_scaling {
ADV7511_CSC_SCALING_1 = 0,
ADV7511_CSC_SCALING_2 = 1,
ADV7511_CSC_SCALING_4 = 2,
};
/**
* struct adv7511_video_config - Describes adv7511 hardware configuration
* @csc_enable: Whether to enable color space conversion
* @csc_scaling_factor: Color space conversion scaling factor
* @csc_coefficents: Color space conversion coefficents
* @hdmi_mode: Whether to use HDMI or DVI output mode
* @avi_infoframe: HDMI infoframe
*/
struct adv7511_video_config {
bool csc_enable;
enum adv7511_csc_scaling csc_scaling_factor;
const uint16_t *csc_coefficents;
bool hdmi_mode;
struct hdmi_avi_infoframe avi_infoframe;
};
#endif /* __DRM_I2C_ADV7511_H__ */
@@ -0,0 +1,313 @@
/*
* Analog Devices ADV7511 HDMI transmitter driver
*
* Copyright 2012 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include "adv7535.h"
static const struct snd_soc_dapm_widget adv7511_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("TMDS"),
SND_SOC_DAPM_AIF_IN("AIFIN", "Playback", 0, SND_SOC_NOPM, 0, 0),
};
static const struct snd_soc_dapm_route adv7511_routes[] = {
{ "TMDS", NULL, "AIFIN" },
};
static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs,
unsigned int *cts, unsigned int *n)
{
switch (fs) {
case 32000:
*n = 4096;
break;
case 44100:
*n = 6272;
break;
case 48000:
*n = 6144;
break;
}
*cts = ((f_tmds * *n) / (128 * fs)) * 1000;
}
static int adv7511_update_cts_n(struct adv7511 *adv7511)
{
unsigned int cts = 0;
unsigned int n = 0;
adv7511_calc_cts_n(adv7511->f_tmds, adv7511->f_audio, &cts, &n);
regmap_write(adv7511->regmap, ADV7511_REG_N0, (n >> 16) & 0xf);
regmap_write(adv7511->regmap, ADV7511_REG_N1, (n >> 8) & 0xff);
regmap_write(adv7511->regmap, ADV7511_REG_N2, n & 0xff);
regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0,
(cts >> 16) & 0xf);
regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1,
(cts >> 8) & 0xff);
regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2,
cts & 0xff);
return 0;
}
static int adv7511_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec);
unsigned int rate;
unsigned int len;
switch (params_rate(params)) {
case 32000:
rate = ADV7511_SAMPLE_FREQ_32000;
break;
case 44100:
rate = ADV7511_SAMPLE_FREQ_44100;
break;
case 48000:
rate = ADV7511_SAMPLE_FREQ_48000;
break;
case 88200:
rate = ADV7511_SAMPLE_FREQ_88200;
break;
case 96000:
rate = ADV7511_SAMPLE_FREQ_96000;
break;
case 176400:
rate = ADV7511_SAMPLE_FREQ_176400;
break;
case 192000:
rate = ADV7511_SAMPLE_FREQ_192000;
break;
default:
return -EINVAL;
}
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
len = ADV7511_I2S_SAMPLE_LEN_16;
break;
case SNDRV_PCM_FORMAT_S18_3LE:
len = ADV7511_I2S_SAMPLE_LEN_18;
break;
case SNDRV_PCM_FORMAT_S20_3LE:
len = ADV7511_I2S_SAMPLE_LEN_20;
break;
case SNDRV_PCM_FORMAT_S24_LE:
len = ADV7511_I2S_SAMPLE_LEN_24;
break;
default:
return -EINVAL;
}
adv7511->f_audio = params_rate(params);
adv7511_update_cts_n(adv7511);
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG3,
ADV7511_AUDIO_CFG3_LEN_MASK, len);
regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
regmap_write(adv7511->regmap, 0x73, 0x1);
return 0;
}
static int adv7511_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec);
unsigned int audio_source, i2s_format = 0;
unsigned int invert_clock;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
audio_source = ADV7511_AUDIO_SOURCE_I2S;
i2s_format = ADV7511_I2S_FORMAT_I2S;
break;
case SND_SOC_DAIFMT_RIGHT_J:
audio_source = ADV7511_AUDIO_SOURCE_I2S;
i2s_format = ADV7511_I2S_FORMAT_RIGHT_J;
break;
case SND_SOC_DAIFMT_LEFT_J:
audio_source = ADV7511_AUDIO_SOURCE_I2S;
i2s_format = ADV7511_I2S_FORMAT_LEFT_J;
break;
// case SND_SOC_DAIFMT_SPDIF:
// audio_source = ADV7511_AUDIO_SOURCE_SPDIF;
// break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
invert_clock = 0;
break;
case SND_SOC_DAIFMT_IB_NF:
invert_clock = 1;
break;
default:
return -EINVAL;
}
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_SOURCE, 0x70,
audio_source << 4);
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(6),
invert_clock << 6);
regmap_update_bits(adv7511->regmap, ADV7511_REG_I2S_CONFIG, 0x03,
i2s_format);
adv7511->audio_source = audio_source;
return 0;
}
static int adv7511_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
switch (level) {
case SND_SOC_BIAS_ON:
switch (adv7511->audio_source) {
case ADV7511_AUDIO_SOURCE_I2S:
break;
case ADV7511_AUDIO_SOURCE_SPDIF:
regmap_update_bits(adv7511->regmap,
ADV7511_REG_AUDIO_CONFIG, BIT(7),
BIT(7));
break;
}
break;
case SND_SOC_BIAS_PREPARE:
if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
adv7511_packet_enable(adv7511,
ADV7511_PACKET_ENABLE_AUDIO_SAMPLE);
adv7511_packet_enable(adv7511,
ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME);
adv7511_packet_enable(adv7511,
ADV7511_PACKET_ENABLE_N_CTS);
} else {
adv7511_packet_disable(adv7511,
ADV7511_PACKET_ENABLE_AUDIO_SAMPLE);
adv7511_packet_disable(adv7511,
ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME);
adv7511_packet_disable(adv7511,
ADV7511_PACKET_ENABLE_N_CTS);
}
break;
case SND_SOC_BIAS_STANDBY:
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
BIT(7), 0);
break;
case SND_SOC_BIAS_OFF:
break;
}
dapm->bias_level = level;
return 0;
}
#define ADV7511_RATES (SNDRV_PCM_RATE_32000 |\
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\
SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
#define ADV7511_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
static const struct snd_soc_dai_ops adv7511_dai_ops = {
.hw_params = adv7511_hw_params,
/*.set_sysclk = adv7511_set_dai_sysclk,*/
.set_fmt = adv7511_set_dai_fmt,
};
static struct snd_soc_dai_driver adv7511_dai = {
.name = "adv7511",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = ADV7511_RATES,
.formats = ADV7511_FORMATS,
},
.ops = &adv7511_dai_ops,
};
static int adv7511_suspend(struct snd_soc_codec *codec)
{
return adv7511_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
static int adv7511_resume(struct snd_soc_codec *codec)
{
return adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
}
static int adv7511_probe(struct snd_soc_codec *codec)
{
return adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
}
static int adv7511_remove(struct snd_soc_codec *codec)
{
adv7511_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static struct snd_soc_codec_driver adv7511_codec_driver = {
.probe = adv7511_probe,
.remove = adv7511_remove,
.suspend = adv7511_suspend,
.resume = adv7511_resume,
.set_bias_level = adv7511_set_bias_level,
.component_driver = {
.dapm_widgets = adv7511_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(adv7511_dapm_widgets),
.dapm_routes = adv7511_routes,
.num_dapm_routes = ARRAY_SIZE(adv7511_routes),
},
};
int adv7511_audio_init(struct device *dev)
{
return snd_soc_register_codec(dev, &adv7511_codec_driver,
&adv7511_dai, 1);
}
void adv7511_audio_exit(struct device *dev)
{
snd_soc_unregister_codec(dev);
}
File diff suppressed because it is too large Load Diff
+139 -5
View File
@@ -11,6 +11,7 @@
#ifndef __KIRIN_DPE_REG_H__
#define __KIRIN_DPE_REG_H__
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/platform_device.h>
@@ -19,10 +20,25 @@
#include <linux/wait.h>
#include <linux/bug.h>
#include <linux/iommu.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/ion.h>
#include <linux/hisi/hisi_ion.h>
#define FB_ACCEL_HI62xx 0x1
#define FB_ACCEL_HI363x 0x2
#define FB_ACCEL_HI365x 0x4
#define FB_ACCEL_HI625x 0x8
#define FB_ACCEL_HI366x 0x10
#define FB_ACCEL_KIRIN970_ES 0x20
#define FB_ACCEL_KIRIN970 0x40
#define FB_ACCEL_KIRIN660 0x80
#define FB_ACCEL_KIRIN980_ES 0x100
#define FB_ACCEL_KIRIN980 0x200
#define FB_ACCEL_PLATFORM_TYPE_FPGA 0x10000000 //FPGA
#define FB_ACCEL_PLATFORM_TYPE_ASIC 0x20000000 //ASIC
/*******************************************************************************
**
*/
@@ -137,11 +153,6 @@ typedef struct drm_dss_layer {
#define DEFAULT_MIPI_CLK_RATE (192 * 100000L)
#define DEFAULT_PCLK_DSI_RATE (120 * 1000000L)
#define DEFAULT_DSS_CORE_CLK_08V_RATE (535000000UL)
#define DEFAULT_DSS_CORE_CLK_07V_RATE (400000000UL)
#define DEFAULT_PCLK_DSS_RATE (114000000UL)
#define DEFAULT_PCLK_PCTRL_RATE (80000000UL)
#define DSS_MAX_PXL0_CLK_288M (288000000UL)
#define DSS_MAX_PXL0_CLK_144M (144000000UL)
#define DSS_ADDR 0xE8600000
@@ -150,6 +161,7 @@ typedef struct drm_dss_layer {
#define PMC_BASE (0xFFF31000)
#define PERI_CRG_BASE (0xFFF35000)
#define SCTRL_BASE (0xFFF0A000)
#define PCTRL_BASE (0xE8A09000)
#define GPIO_LCD_POWER_1V2 (54)
#define GPIO_LCD_STANDBY (67)
@@ -174,6 +186,9 @@ typedef struct drm_dss_layer {
#define DEFAULT_DSS_CORE_CLK_08V_RATE (535000000UL)
#define DEFAULT_DSS_CORE_CLK_07V_RATE (400000000UL)
#define DEFAULT_DSS_CORE_CLK_RATE_L1 (300000000UL)
#define DEFAULT_DSS_MMBUF_CLK_RATE_L1 (238000000UL)
#define DEFAULT_PCLK_DSS_RATE (114000000UL)
#define DEFAULT_PCLK_PCTRL_RATE (80000000UL)
#define DSS_MAX_PXL0_CLK_288M (288000000UL)
@@ -206,6 +221,25 @@ typedef struct drm_dss_layer {
#define PERF_SAMPSTOP_REG (0x10)
#define DEVMEM_PERF_SIZE (0x100)
/* dp clock used for hdmi */
#define DEFAULT_AUXCLK_DPCTRL_RATE 16000000UL
#define DEFAULT_ACLK_DPCTRL_RATE_ES 288000000UL
#define DEFAULT_ACLK_DPCTRL_RATE_CS 207000000UL
#define DEFAULT_MIDIA_PPLL7_CLOCK_FREQ 1782000000UL
#define KIRIN970_VCO_MIN_FREQ_OUPUT 1000000 /*Boston: 1000 * 1000*/
#define KIRIN970_SYS_19M2 19200 /*Boston: 19.2f * 1000 */
#define MIDIA_PPLL7_CTRL0 0x50c
#define MIDIA_PPLL7_CTRL1 0x510
#define MIDIA_PPLL7_FREQ_DEVIDER_MASK GENMASK(25, 2)
#define MIDIA_PPLL7_FRAC_MODE_MASK GENMASK(25, 0)
#define ACCESS_REGISTER_FN_MAIN_ID_HDCP 0xc500aa01
#define ACCESS_REGISTER_FN_SUB_ID_HDCP_CTRL (0x55bbccf1)
#define ACCESS_REGISTER_FN_SUB_ID_HDCP_INT (0x55bbccf2)
/*
* DSS Registers
*/
@@ -1464,6 +1498,8 @@ typedef struct dss_dfc {
#define SCF_RD_SHADOW (0x00F0)
#define SCF_CLK_SEL (0x00F8)
#define SCF_CLK_EN (0x00FC)
#define WCH_SCF_COEF_MEM_CTRL (0x0218)
#define WCH_SCF_LB_MEM_CTRL (0x290)
/* MACROS */
#define SCF_MIN_INPUT (16)
@@ -1690,6 +1726,21 @@ typedef struct dss_csc {
#define AFBCD_MONITOR_REG2_OFFSET (0x94C)
#define AFBCD_MONITOR_REG3_OFFSET (0x950)
#define AFBCD_DEBUG_REG0_OFFSET (0x954)
#define AFBCD_CREG_FBCD_CTRL_MODE (0x960)
#define AFBCD_HREG_HDR_PTR_L1 (0x964)
#define AFBCD_HREG_PLD_PTR_L1 (0x968)
#define AFBCD_HEADER_SRTIDE_1 (0x96C)
#define AFBCD_PAYLOAD_SRTIDE_1 (0x970)
#define AFBCD_HREG_HDR_PTR_L1 (0x964)
#define AFBCD_HREG_PLD_PTR_L1 (0x968)
#define AFBCD_HEADER_SRTIDE_1 (0x96C)
#define AFBCD_PAYLOAD_SRTIDE_1 (0x970)
#define AFBCD_BLOCK_TYPE (0x974)
#define AFBCD_MM_BASE_1 (0x978)
#define AFBCD_MM_BASE_2 (0x97C)
#define AFBCD_MM_BASE_3 (0x980)
#define HFBCD_MEM_CTRL (0x984)
#define HFBCD_MEM_CTRL_1 (0x988)
#define AFBCE_HREG_PIC_BLKS (0x900)
#define AFBCE_HREG_FORMAT (0x904)
@@ -1705,6 +1756,13 @@ typedef struct dss_csc {
#define AFBCE_THRESHOLD (0x92C)
#define AFBCE_SCRAMBLE_MODE (0x930)
#define AFBCE_HEADER_POINTER_OFFSET (0x934)
#define AFBCE_CREG_FBCE_CTRL_MODE (0x950)
#define AFBCE_HREG_HDR_PTR_L1 (0x954)
#define AFBCE_HREG_PLD_PTR_L1 (0x958)
#define AFBCE_HEADER_SRTIDE_1 (0x95C)
#define AFBCE_PAYLOAD_SRTIDE_1 (0x960)
#define AFBCE_MEM_CTRL_1 (0x968)
#define FBCD_CREG_FBCD_CTRL_GATE (0x98C)
#define ROT_FIRST_LNS (0x530)
#define ROT_STATE (0x534)
@@ -2255,6 +2313,47 @@ typedef struct dss_mctl_sys {
#define OVL_6LAYER_NUM (6)
#define OVL_2LAYER_NUM (2)
/*******************************************************************************
** OVL
*/
#define OV_SIZE (0x000)
#define OV_BG_COLOR_RGB (0x004)
#define OV_BG_COLOR_A (0x008)
#define OV_DST_STARTPOS (0x00C)
#define OV_DST_ENDPOS (0x010)
#define OV_GCFG (0x014)
#define OV_LAYER0_POS (0x030)
#define OV_LAYER0_SIZE (0x034)
#define OV_LAYER0_SRCLOKEY (0x038)
#define OV_LAYER0_SRCHIKEY (0x03C)
#define OV_LAYER0_DSTLOKEY (0x040)
#define OV_LAYER0_DSTHIKEY (0x044)
#define OV_LAYER0_PATTERN_RGB (0x048)
#define OV_LAYER0_PATTERN_A (0x04C)
#define OV_LAYER0_ALPHA_MODE (0x050)
#define OV_LAYER0_ALPHA_A (0x054)
#define OV_LAYER0_CFG (0x058)
#define OV_LAYER0_PSPOS (0x05C)
#define OV_LAYER0_PEPOS (0x060)
#define OV_LAYER0_INFO_ALPHA (0x064)
#define OV_LAYER0_INFO_SRCCOLOR (0x068)
#define OV_LAYER0_DBG_INFO (0x06C)
#define OV8_BASE_DBG_INFO (0x340)
#define OV8_RD_SHADOW_SEL (0x344)
#define OV8_CLK_SEL (0x348)
#define OV8_CLK_EN (0x34C)
#define OV8_BLOCK_SIZE (0x350)
#define OV8_BLOCK_DBG (0x354)
#define OV8_REG_DEFAULT (0x358)
#define OV2_BASE_DBG_INFO (0x200)
#define OV2_RD_SHADOW_SEL (0x204)
#define OV2_CLK_SEL (0x208)
#define OV2_CLK_EN (0x20C)
#define OV2_BLOCK_SIZE (0x210)
#define OV2_BLOCK_DBG (0x214)
#define OV2_REG_DEFAULT (0x218)
#define OV_8LAYER_NUM (8)
typedef struct dss_ovl_layer {
u32 layer_pos;
u32 layer_size;
@@ -2331,6 +2430,8 @@ typedef struct dss_ovl_alpha {
#define DBUF_THD_DFS_OK (0x0068)
#define DBUF_FLUX_REQ_CTRL (0x006C)
#define DBUF_REG_DEFAULT (0x00A4)
#define DBUF_DFS_RAM_MANAGE (0x00A8)
#define DBUF_DFS_DATA_FILL_OUT (0x00AC)
/*******************************************************************************
** DPP
@@ -2840,6 +2941,19 @@ typedef struct dss_arsr1p {
#define MIPIDSI_PHY_STATUS_OFFSET (0x00b0)
#define MIPIDSI_PHY_TST_CTRL0_OFFSET (0x00b4)
#define MIPIDSI_PHY_TST_CTRL1_OFFSET (0x00b8)
#define MIPIDSI_PHY_TST_CLK_PRE_DELAY (0x00B0)
#define MIPIDSI_PHY_TST_CLK_POST_DELAY (0x00B1)
#define MIPIDSI_PHY_TST_CLK_TLPX (0x00B2)
#define MIPIDSI_PHY_TST_CLK_PREPARE (0x00B3)
#define MIPIDSI_PHY_TST_CLK_ZERO (0x00B4)
#define MIPIDSI_PHY_TST_CLK_TRAIL (0x00B5)
#define MIPIDSI_PHY_TST_DATA_PRE_DELAY (0x0070)
#define MIPIDSI_PHY_TST_DATA_POST_DELAY (0x0071)
#define MIPIDSI_PHY_TST_DATA_TLPX (0x0072)
#define MIPIDSI_PHY_TST_DATA_PREPARE (0x0073)
#define MIPIDSI_PHY_TST_DATA_ZERO (0x0074)
#define MIPIDSI_PHY_TST_DATA_TRAIL (0x0075)
#define MIPIDSI_PHY_TST_LANE_TRANSMISSION_PROPERTY (0x0077)
#define MIPIDSI_INT_ST0_OFFSET (0x00bc)
#define MIPIDSI_INT_ST1_OFFSET (0x00c0)
#define MIPIDSI_INT_MSK0_OFFSET (0x00c4)
@@ -2931,11 +3045,16 @@ struct dss_hw_ctx {
void __iomem *base;
struct regmap *noc_regmap;
struct reset_control *reset;
u32 g_dss_version_tag;
void __iomem *noc_dss_base;
void __iomem *peri_crg_base;
void __iomem *pmc_base;
void __iomem *sctrl_base;
void __iomem *media_crg_base;
void __iomem *pctrl_base;
void __iomem *mmbuf_crg_base;
void __iomem *pmctrl_base;
struct clk *dss_axi_clk;
struct clk *dss_pclk_dss_clk;
@@ -2945,6 +3064,12 @@ struct dss_hw_ctx {
struct clk *dss_mmbuf_clk;
struct clk *dss_pclk_mmbuf_clk;
struct dss_clk_rate *dss_clk;
struct regulator *dpe_regulator;
struct regulator_bulk_data *mmbuf_regulator;
struct regulator_bulk_data *media_subsys_regulator;
bool power_on;
int irq;
@@ -2962,6 +3087,15 @@ struct dss_hw_ctx {
unsigned long screen_size;
};
typedef struct dss_clk_rate {
uint64_t dss_pri_clk_rate;
uint64_t dss_pclk_dss_rate;
uint64_t dss_pclk_pctrl_rate;
uint64_t dss_mmbuf_rate;
uint32_t dss_voltage_value; //0:0.7v, 2:0.8v
uint32_t reserved;
} dss_clk_rate_t;
struct dss_crtc {
struct drm_crtc base;
struct dss_hw_ctx *ctx;
+349 -19
View File
@@ -17,6 +17,10 @@
int g_debug_set_reg_val = 0;
DEFINE_SEMAPHORE(hisi_fb_dss_regulator_sem);
static int dss_regulator_refcount;
extern u32 g_dss_module_ovl_base[DSS_MCTL_IDX_MAX][MODULE_OVL_MAX];
mipi_ifbc_division_t g_mipi_ifbc_division[MIPI_DPHY_NUM][IFBC_TYPE_MAX] = {
@@ -104,6 +108,39 @@ void set_reg(char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs)
}
}
uint32_t set_bits32(uint32_t old_val, uint32_t val, uint8_t bw, uint8_t bs)
{
uint32_t mask = (1UL << bw) - 1UL;
uint32_t tmp = 0;
tmp = old_val;
tmp &= ~(mask << bs);
return (tmp | ((val & mask) << bs));
}
struct dss_clk_rate *get_dss_clk_rate(struct dss_hw_ctx *ctx)
{
struct dss_clk_rate *pdss_clk_rate = NULL;
uint64_t default_dss_pri_clk_rate;
if (ctx == NULL) {
DRM_ERROR("ctx is null.\n");
return pdss_clk_rate;
}
pdss_clk_rate = &(ctx->dss_clk);
default_dss_pri_clk_rate = DEFAULT_DSS_CORE_CLK_RATE_L1;
pdss_clk_rate->dss_pri_clk_rate = default_dss_pri_clk_rate;
pdss_clk_rate->dss_mmbuf_rate = DEFAULT_DSS_MMBUF_CLK_RATE_L1;
pdss_clk_rate->dss_pclk_dss_rate = DEFAULT_PCLK_DSS_RATE;
pdss_clk_rate->dss_pclk_pctrl_rate = DEFAULT_PCLK_PCTRL_RATE;
return pdss_clk_rate;
}
static int mipi_ifbc_get_rect(struct dss_rect *rect)
{
u32 ifbc_type;
@@ -260,7 +297,7 @@ void init_ldi(struct dss_crtc *acrtc)
/* for 1Hz LCD and mipi command LCD*/
set_reg(ldi_base + LDI_DSI_CMD_MOD_CTRL, 0x1, 1, 1);
/*ldi_data_gate(hisifd, true);*/
/*ldi_data_gate(ctx, true);*/
#ifdef CONFIG_HISI_FB_LDI_COLORBAR_USED
/* colorbar width*/
@@ -309,6 +346,7 @@ void init_dbuf(struct dss_crtc *acrtc)
int dfs_time = 0;
int dfs_time_min = 0;
int depth = 0;
int dfs_ram = 0;
ctx = acrtc->ctx;
if (!ctx) {
@@ -328,10 +366,13 @@ void init_dbuf(struct dss_crtc *acrtc)
dbuf_base = ctx->base + DSS_DBUF0_OFFSET;
if (mode->hdisplay * mode->vdisplay >= RES_4K_PHONE)
if (mode->hdisplay * mode->vdisplay >= RES_4K_PHONE) {
dfs_time_min = DFS_TIME_MIN_4K;
else
dfs_ram = 0x0;
} else {
dfs_time_min = DFS_TIME_MIN;
dfs_ram = 0xF00;
}
dfs_time = DFS_TIME;
depth = DBUF0_DEPTH;
@@ -341,6 +382,9 @@ void init_dbuf(struct dss_crtc *acrtc)
"hsw=%d\n"
"hbp=%d\n"
"hfp=%d\n"
"vfp = %d\n"
"vbp = %d\n"
"vsw = %d\n"
"mode->hdisplay=%d\n"
"mode->vdisplay=%d\n",
dfs_time,
@@ -348,6 +392,9 @@ void init_dbuf(struct dss_crtc *acrtc)
hsw,
hbp,
hfp,
vfp,
vbp,
vsw,
mode->hdisplay,
mode->vdisplay);
@@ -420,6 +467,9 @@ void init_dbuf(struct dss_crtc *acrtc)
outp32(dbuf_base + DBUF_FLUX_REQ_CTRL, (dfs_ok_mask << 1) | thd_flux_req_sw_en);
outp32(dbuf_base + DBUF_DFS_LP_CTRL, 0x1);
if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
outp32(dbuf_base + DBUF_DFS_RAM_MANAGE, dfs_ram);
}
}
void init_dpp(struct dss_crtc *acrtc)
@@ -430,6 +480,7 @@ void init_dpp(struct dss_crtc *acrtc)
char __iomem *dpp_base;
char __iomem *mctl_sys_base;
DRM_INFO("+. \n");
ctx = acrtc->ctx;
if (!ctx) {
DRM_ERROR("ctx is NULL!\n");
@@ -448,8 +499,14 @@ void init_dpp(struct dss_crtc *acrtc)
(DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay));
#ifdef CONFIG_HISI_FB_DPP_COLORBAR_USED
#if defined (CONFIG_HISI_FB_970)
outp32(dpp_base + DPP_CLRBAR_CTRL, (0x30 << 24) | (0 << 1) | 0x1);
set_reg(dpp_base + DPP_CLRBAR_1ST_CLR, 0x3FF00000, 30, 0); //Red
set_reg(dpp_base + DPP_CLRBAR_2ND_CLR, 0x000FFC00, 30, 0); //Green
set_reg(dpp_base + DPP_CLRBAR_3RD_CLR, 0x000003FF, 30, 0); //Blue
#else
void __iomem *mctl_base;
outp32(dpp_base + DPP_CLRBAR_CTRL, (0x30 << 24) |(0 << 1) | 0x1);
outp32(dpp_base + DPP_CLRBAR_CTRL, (0x30 << 24) | (0 << 1) | 0x1);
set_reg(dpp_base + DPP_CLRBAR_1ST_CLR, 0xFF, 8, 16);
set_reg(dpp_base + DPP_CLRBAR_2ND_CLR, 0xFF, 8, 8);
set_reg(dpp_base + DPP_CLRBAR_3RD_CLR, 0xFF, 8, 0);
@@ -465,7 +522,10 @@ void init_dpp(struct dss_crtc *acrtc)
set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 2, 0);
set_reg(mctl_sys_base + MCTL_OV0_FLUSH_EN, 0x8, 4, 0);
set_reg(mctl_base + MCTL_CTL_MUTEX, 0x0, 1, 0);
#endif
#endif
DRM_INFO("-. \n");
}
void enable_ldi(struct dss_crtc *acrtc)
@@ -550,13 +610,14 @@ void dpe_interrupt_unmask(struct dss_crtc *acrtc)
dss_base = ctx->base;
unmask = ~0;
unmask &= ~(BIT_DPP_INTS | BIT_ITF0_INTS | BIT_MMU_IRPT_NS);
unmask &= ~(BIT_ITF0_INTS | BIT_MMU_IRPT_NS);
outp32(dss_base + GLB_CPU_PDP_INT_MSK, unmask);
unmask = ~0;
unmask &= ~(BIT_VSYNC | BIT_VACTIVE0_END | BIT_LDI_UNFLOW);
outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, unmask);
}
void dpe_interrupt_mask(struct dss_crtc *acrtc)
@@ -620,12 +681,10 @@ int dpe_init(struct dss_crtc *acrtc)
return 0;
}
void dss_inner_clk_pdp_enable(struct dss_crtc *acrtc)
void dss_inner_clk_pdp_enable(struct dss_hw_ctx *ctx)
{
struct dss_hw_ctx *ctx;
char __iomem *dss_base;
ctx = acrtc->ctx;
if (!ctx) {
DRM_ERROR("ctx is NULL!\n");
return;
@@ -639,16 +698,74 @@ void dss_inner_clk_pdp_enable(struct dss_crtc *acrtc)
outp32(dss_base + DSS_DPP_DITHER_OFFSET + DITHER_MEM_CTRL, 0x00000008);
}
void dss_inner_clk_common_enable(struct dss_crtc *acrtc)
static void dss_normal_set_reg(char __iomem *dss_base)
{
struct dss_hw_ctx *ctx;
char __iomem *dss_base;
ctx = acrtc->ctx;
if (!ctx) {
DRM_ERROR("ctx is NULL!\n");
if (NULL == dss_base) {
DRM_ERROR("dss_base is null.\n");
return;
}
//core/axi/mmbuf
outp32(dss_base + DSS_CMDLIST_OFFSET + CMD_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);
outp32(dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_VG0_ARSR_OFFSET + ARSR2P_LB_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + VPP_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);
outp32(dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);
outp32(dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);
outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + HFBCD_MEM_CTRL, 0x88888888);
outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + HFBCD_MEM_CTRL_1, 0x00000888);
outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + HFBCD_MEM_CTRL, 0x88888888);
outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + HFBCD_MEM_CTRL_1, 0x00000888);
outp32(dss_base + DSS_RCH_VG2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);
outp32(dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x0000008);
outp32(dss_base + DSS_RCH_G0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_G0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);
outp32(dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);
outp32(dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x0000008);
outp32(dss_base + DSS_RCH_G1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_G1_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);
outp32(dss_base + DSS_RCH_D0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_D0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);
outp32(dss_base + DSS_RCH_D1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_D2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_RCH_D3_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_WCH0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_WCH0_DMA_OFFSET + AFBCE_MEM_CTRL, 0x00000888);
outp32(dss_base + DSS_WCH0_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_WCH1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_WCH1_DMA_OFFSET + AFBCE_MEM_CTRL, 0x88888888);
outp32(dss_base + DSS_WCH1_DMA_OFFSET + AFBCE_MEM_CTRL_1, 0x00000088);
outp32(dss_base + DSS_WCH1_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);
outp32(dss_base + DSS_WCH1_DMA_OFFSET + WCH_SCF_COEF_MEM_CTRL, 0x00000088);
outp32(dss_base + DSS_WCH1_DMA_OFFSET + WCH_SCF_LB_MEM_CTRL, 0x00000088);
outp32(dss_base + GLB_DSS_MEM_CTRL, 0x02605550);
}
void dss_inner_clk_common_enable(struct dss_hw_ctx *ctx)
{
char __iomem *dss_base;
if (NULL == ctx) {
DRM_ERROR("NULL Pointer!\n");
return -EINVAL;
}
dss_base = ctx->base;
/*core/axi/mmbuf*/
@@ -666,8 +783,16 @@ void dss_inner_clk_common_enable(struct dss_crtc *acrtc)
outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_v1 ,dma_buf mem*/
outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_v1 ,afbcd mem*/
outp32(dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_v2 ,scf mem*/
outp32(dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);/*rch_v2 ,scf mem*/
if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + HFBCD_MEM_CTRL, 0x88888888);
outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + HFBCD_MEM_CTRL_1, 0x00000888);
outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + HFBCD_MEM_CTRL, 0x88888888);
outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + HFBCD_MEM_CTRL_1, 0x00000888);
} else {
outp32(dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_v2 ,scf mem*/
outp32(dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);/*rch_v2 ,scf mem*/
}
outp32(dss_base + DSS_RCH_VG2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_v2 ,dma_buf mem*/
outp32(dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_g0 ,scf mem*/
@@ -692,9 +817,18 @@ void dss_inner_clk_common_enable(struct dss_crtc *acrtc)
outp32(dss_base + DSS_WCH1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*wch1 DMA/AFBCE mem*/
outp32(dss_base + DSS_WCH1_DMA_OFFSET + AFBCE_MEM_CTRL, 0x00000888);/*wch1 DMA/AFBCE mem*/
outp32(dss_base + DSS_WCH1_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);/*wch1 rot mem*/
outp32(dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*wch2 DMA/AFBCE mem*/
outp32(dss_base + DSS_WCH2_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);/*wch2 rot mem*/
if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
outp32(dss_base + DSS_WCH1_DMA_OFFSET + WCH_SCF_COEF_MEM_CTRL, 0x00000088);
outp32(dss_base + DSS_WCH1_DMA_OFFSET + WCH_SCF_LB_MEM_CTRL, 0x00000008);
outp32(dss_base + GLB_DSS_MEM_CTRL, 0x02605550);
} else {
outp32(dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*wch2 DMA/AFBCE mem*/
outp32(dss_base + DSS_WCH2_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);/*wch2 rot mem*/
//outp32(dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
//outp32(dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
}
}
int dpe_irq_enable(struct dss_crtc *acrtc)
{
struct dss_hw_ctx *ctx;
@@ -728,3 +862,199 @@ int dpe_irq_disable(struct dss_crtc *acrtc)
return 0;
}
void mds_regulator_enable(struct dss_hw_ctx *ctx)
{
int ret = 0;
if (NULL == ctx) {
DRM_ERROR("NULL ptr.\n");
return -EINVAL;
}
ret = regulator_bulk_enable(1, ctx->media_subsys_regulator);
if (ret) {
DRM_ERROR(" media subsys regulator_enable failed, error=%d!\n", ret);
}
return ret;
}
int dpe_common_clk_enable(struct dss_hw_ctx *ctx)
{
int ret = 0;
struct clk *clk_tmp = NULL;
if (ctx == NULL) {
DRM_ERROR("ctx is NULL point!\n");
return -EINVAL;
}
clk_tmp = ctx->dss_mmbuf_clk;
if (clk_tmp) {
ret = clk_prepare(clk_tmp);
if (ret) {
DRM_ERROR(" dss_mmbuf_clk clk_prepare failed, error=%d!\n", ret);
return -EINVAL;
}
ret = clk_enable(clk_tmp);
if (ret) {
DRM_ERROR(" dss_mmbuf_clk clk_enable failed, error=%d!\n", ret);
return -EINVAL;
}
}
clk_tmp = ctx->dss_axi_clk;
if (clk_tmp) {
ret = clk_prepare(clk_tmp);
if (ret) {
DRM_ERROR(" dss_axi_clk clk_prepare failed, error=%d!\n", ret);
return -EINVAL;
}
ret = clk_enable(clk_tmp);
if (ret) {
DRM_ERROR(" dss_axi_clk clk_enable failed, error=%d!\n", ret);
return -EINVAL;
}
}
clk_tmp = ctx->dss_pclk_dss_clk;
if (clk_tmp) {
ret = clk_prepare(clk_tmp);
if (ret) {
DRM_ERROR(" dss_pclk_dss_clk clk_prepare failed, error=%d!\n", ret);
return -EINVAL;
}
ret = clk_enable(clk_tmp);
if (ret) {
DRM_ERROR(" dss_pclk_dss_clk clk_enable failed, error=%d!\n", ret);
return -EINVAL;
}
}
return 0;
}
int dpe_inner_clk_enable(struct dss_hw_ctx *ctx)
{
int ret = 0;
struct clk *clk_tmp = NULL;
if (ctx == NULL) {
DRM_ERROR("ctx is NULL point!\n");
return -EINVAL;
}
clk_tmp = ctx->dss_pri_clk;
if (clk_tmp) {
ret = clk_prepare(clk_tmp);
if (ret) {
DRM_ERROR(" dss_pri_clk clk_prepare failed, error=%d!\n", ret);
return -EINVAL;
}
ret = clk_enable(clk_tmp);
if (ret) {
DRM_ERROR(" dss_pri_clk clk_enable failed, error=%d!\n", ret);
return -EINVAL;
}
}
clk_tmp = ctx->dss_pxl0_clk;
if (clk_tmp) {
ret = clk_prepare(clk_tmp);
if (ret) {
DRM_ERROR(" dss_pxl0_clk clk_prepare failed, error=%d!\n", ret);
return -EINVAL;
}
ret = clk_enable(clk_tmp);
if (ret) {
DRM_ERROR(" dss_pxl0_clk clk_enable failed, error=%d!\n", ret);
return -EINVAL;
}
}
return 0;
}
int dpe_regulator_enable(struct dss_hw_ctx *ctx)
{
int ret = 0;
DRM_INFO("+. \n");
if (NULL == ctx) {
DRM_ERROR("NULL ptr.\n");
return -EINVAL;
}
ret = regulator_enable(ctx->dpe_regulator);
if (ret) {
DRM_ERROR(" dpe regulator_enable failed, error=%d!\n", ret);
return -EINVAL;
}
DRM_INFO("-. \n");
return ret;
}
int dpe_set_clk_rate(struct dss_hw_ctx *ctx)
{
struct dss_clk_rate *pdss_clk_rate = NULL;
uint64_t dss_pri_clk_rate;
uint64_t dss_mmbuf_rate;
int ret = 0;
DRM_INFO("+. \n");
if (NULL == ctx) {
DRM_ERROR("NULL Pointer!\n");
return -EINVAL;
}
pdss_clk_rate = get_dss_clk_rate(ctx);
if (NULL == pdss_clk_rate) {
DRM_ERROR("NULL Pointer!\n");
return -EINVAL;
}
dss_pri_clk_rate = pdss_clk_rate->dss_pri_clk_rate;
ret = clk_set_rate(ctx->dss_pri_clk, dss_pri_clk_rate);
if (ret < 0) {
DRM_ERROR("dss_pri_clk clk_set_rate(%llu) failed, error=%d!\n",
dss_pri_clk_rate, ret);
return -EINVAL;
}
DRM_INFO("dss_pri_clk:[%llu]->[%llu].\n",
dss_pri_clk_rate, (uint64_t)clk_get_rate(ctx->dss_pri_clk));
#if 0 /* it will be set on dss_ldi_set_mode func */
ret = clk_set_rate(ctx->dss_pxl0_clk, pinfo->pxl_clk_rate);
if (ret < 0) {
DRM_ERROR("fb%d dss_pxl0_clk clk_set_rate(%llu) failed, error=%d!\n",
ctx->index, pinfo->pxl_clk_rate, ret);
if (g_fpga_flag == 0) {
return -EINVAL;
}
}
DRM_INFO("dss_pxl0_clk:[%llu]->[%llu].\n",
pinfo->pxl_clk_rate, (uint64_t)clk_get_rate(ctx->dss_pxl0_clk));
#endif
dss_mmbuf_rate = pdss_clk_rate->dss_mmbuf_rate;
ret = clk_set_rate(ctx->dss_mmbuf_clk, dss_mmbuf_rate);
if (ret < 0) {
DRM_ERROR("dss_mmbuf clk_set_rate(%llu) failed, error=%d!\n",
dss_mmbuf_rate, ret);
return -EINVAL;
}
DRM_INFO("dss_mmbuf_clk:[%llu]->[%llu].\n",
dss_mmbuf_rate, (uint64_t)clk_get_rate(ctx->dss_mmbuf_clk));
return ret;
}
@@ -14,13 +14,19 @@
#ifndef KIRIN_DRM_DPE_UTILS_H
#define KIRIN_DRM_DPE_UTILS_H
#if defined (CONFIG_HISI_FB_970)
#include "kirin970_dpe_reg.h"
#else
#include "kirin_dpe_reg.h"
#endif
#include "kirin_drm_drv.h"
/*#define CONFIG_HISI_FB_OV_BASE_USED*/
/*#define CONFIG_HISI_FB_DPP_COLORBAR_USED*/
/*#define CONFIG_HISI_FB_LDI_COLORBAR_USED*/
void set_reg(char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs);
uint32_t set_bits32(uint32_t old_val, uint32_t val, uint8_t bw, uint8_t bs);
void init_dbuf(struct dss_crtc *acrtc);
void init_dpp(struct dss_crtc *acrtc);
@@ -31,11 +37,15 @@ void deinit_ldi(struct dss_crtc *acrtc);
void enable_ldi(struct dss_crtc *acrtc);
void disable_ldi(struct dss_crtc *acrtc);
void dss_inner_clk_pdp_enable(struct dss_crtc *acrtc);
void dss_inner_clk_common_enable(struct dss_crtc *acrtc);
void dss_inner_clk_pdp_enable(struct dss_hw_ctx *ctx);
void dss_inner_clk_common_enable(struct dss_hw_ctx *ctx);
void dpe_interrupt_clear(struct dss_crtc *acrtc);
void dpe_interrupt_unmask(struct dss_crtc *acrtc);
void dpe_interrupt_mask(struct dss_crtc *acrtc);
int dpe_common_clk_enable(struct dss_hw_ctx *ctx);
int dpe_inner_clk_enable(struct dss_hw_ctx *ctx);
int dpe_regulator_enable(struct dss_hw_ctx *ctx);
int dpe_set_clk_rate(struct dss_hw_ctx *ctx);
int dpe_irq_enable(struct dss_crtc *acrtc);
int dpe_irq_disable(struct dss_crtc *acrtc);
@@ -51,7 +61,7 @@ int hisi_dss_mctl_mutex_unlock(struct dss_hw_ctx *ctx);
int hisi_dss_ovl_base_config(struct dss_hw_ctx *ctx, u32 xres, u32 yres);
void hisi_fb_pan_display(struct drm_plane *plane);
void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer);
void hisi_dss_online_play(struct kirin_fbdev *fbdev, struct drm_plane *plane, drm_dss_layer_t *layer);
u32 dss_get_format(u32 pixel_format);
+24 -3
View File
@@ -26,7 +26,6 @@
#include "kirin_drm_drv.h"
#ifdef CONFIG_DRM_FBDEV_EMULATION
static bool fbdev = true;
MODULE_PARM_DESC(fbdev, "Enable fbdev compat layer");
@@ -61,10 +60,24 @@ static void kirin_fbdev_output_poll_changed(struct drm_device *dev)
dsi_set_output_client(dev);
#ifdef CMA_BUFFER_USED
if (priv->fbdev) {
DRM_INFO("hotplug_event!!!!!!\n");
drm_fbdev_cma_hotplug_event(priv->fbdev);
} else {
DRM_INFO("cma_init!!!!!!\n");
priv->fbdev = drm_fbdev_cma_init(dev, 32,
dev->mode_config.num_crtc,
dev->mode_config.num_connector);
if (IS_ERR(priv->fbdev))
priv->fbdev = NULL;
}
#else
if (priv->fbdev)
drm_fb_helper_hotplug_event(priv->fbdev);
else
priv->fbdev = kirin_drm_fbdev_init(dev);
#endif
}
static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs = {
@@ -125,14 +138,16 @@ static int kirin_drm_kms_init(struct drm_device *dev)
/* reset all the states of crtc/plane/encoder/connector */
drm_mode_config_reset(dev);
//if (fbdev)
// priv->fbdev = kirin_drm_fbdev_init(dev);
if (fbdev)
priv->fbdev = kirin_drm_fbdev_init(dev);
/* init kms poll for handling hpd */
drm_kms_helper_poll_init(dev);
#if 0
/* force detection after connectors init */
(void)drm_helper_hpd_irq_event(dev);
#endif
return 0;
@@ -336,10 +351,13 @@ static int kirin_drm_platform_probe(struct platform_device *pdev)
return -EINVAL;
}
DRM_INFO("the device node is %s\n", np->name);
remote = kirin_get_remote_node(np);
if (IS_ERR(remote))
return PTR_ERR(remote);
DRM_INFO("the device remote node is %s\n", remote->name);
component_match_add(dev, &match, compare_of, remote);
return component_master_add_with_match(dev, &kirin_drm_ops, match);
@@ -358,6 +376,9 @@ static const struct of_device_id kirin_drm_dt_ids[] = {
{ .compatible = "hisilicon,hi3660-dpe",
.data = &dss_dc_ops,
},
{ .compatible = "hisilicon,kirin970-dpe",
.data = &dss_dc_ops,
},
{ /* end node */ },
};
MODULE_DEVICE_TABLE(of, kirin_drm_dt_ids);
@@ -22,6 +22,7 @@
#define MAX_CRTC 2
//#define CMA_BUFFER_USED
#define to_kirin_fbdev(x) container_of(x, struct kirin_fbdev, fb_helper)
/* display controller init/cleanup ops */
@@ -57,5 +58,4 @@ struct drm_framebuffer *kirin_framebuffer_init(struct drm_device *dev,
struct drm_fb_helper *kirin_drm_fbdev_init(struct drm_device *dev);
void kirin_drm_fbdev_fini(struct drm_device *dev);
#endif /* __KIRIN_DRM_DRV_H__ */
+306 -63
View File
@@ -38,10 +38,21 @@
#include "kirin_drm_drv.h"
#include "kirin_drm_dpe_utils.h"
#if defined (CONFIG_HISI_FB_970)
#include "kirin970_dpe_reg.h"
#else
#include "kirin_dpe_reg.h"
#endif
#define DSS_POWER_UP_ON_UEFI
#if defined (CONFIG_HISI_FB_970)
#define DTS_COMP_DSS_NAME "hisilicon,kirin970-dpe"
#else
#define DTS_COMP_DSS_NAME "hisilicon,hi3660-dpe"
#endif
#define PPLL7_USED_IN_DRV
#define DSS_DEBUG 0
static const struct dss_format dss_formats[] = {
@@ -91,41 +102,215 @@ u32 dss_get_format(u32 pixel_format)
return HISI_FB_PIXEL_FORMAT_UNSUPPORT;
}
#ifdef PPLL7_USED_IN_DRV
/*******************************************************************************
**
*/
int hdmi_ceil(uint64_t a, uint64_t b)
{
if (b == 0)
return -1;
if (a%b != 0) {
return a/b + 1;
} else {
return a/b;
}
}
int hdmi_pxl_ppll7_init(struct dss_hw_ctx *ctx, uint64_t pixel_clock)
{
uint64_t refdiv, fbdiv, frac, postdiv1, postdiv2;
uint64_t vco_min_freq_output = KIRIN970_VCO_MIN_FREQ_OUPUT;
uint64_t sys_clock_fref = KIRIN970_SYS_19M2;
uint64_t ppll7_freq_divider;
uint64_t vco_freq_output;
uint64_t frac_range = 0x1000000;/*2^24*/
uint64_t pixel_clock_ori;
uint64_t pixel_clock_cur;
uint32_t ppll7ctrl0;
uint32_t ppll7ctrl1;
uint32_t ppll7ctrl0_val;
uint32_t ppll7ctrl1_val;
int i, ret;
int ceil_temp;
int freq_divider_list[22] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
12, 14, 15, 16, 20, 21, 24,
25, 30, 36, 42, 49};
int postdiv1_list[22] = {1, 2, 3, 4, 5, 6, 7, 4, 3, 5,
4, 7, 5, 4, 5, 7, 6, 5, 6, 6,
7, 7};
int postdiv2_list[22] = {1, 1, 1, 1, 1, 1, 1, 2, 3, 2,
3, 2, 3, 4, 4, 3, 4, 5, 5, 6,
6, 7};
ret = 0;
postdiv1 = 0;
postdiv2 = 0;
if (pixel_clock == 0)
return -EINVAL;
if (ctx == NULL) {
DRM_ERROR("NULL Pointer\n");
return -EINVAL;
}
pixel_clock_ori = pixel_clock;
if (pixel_clock_ori <= 255000000)
pixel_clock_cur = pixel_clock * 7;
else if (pixel_clock_ori <= 415000000)
pixel_clock_cur = pixel_clock * 5;
else if (pixel_clock_ori <= 594000000)
pixel_clock_cur = pixel_clock * 3;
else {
DRM_ERROR("Clock don't support!!\n");
return -EINVAL;
}
pixel_clock_cur = pixel_clock_cur / 1000;
ceil_temp = hdmi_ceil(vco_min_freq_output, pixel_clock_cur);
if (ceil_temp < 0)
return -EINVAL;
ppll7_freq_divider = (uint64_t)ceil_temp;
for (i = 0; i < 22; i++) {
if (freq_divider_list[i] >= ppll7_freq_divider) {
ppll7_freq_divider = freq_divider_list[i];
postdiv1 = postdiv1_list[i];
postdiv2 = postdiv2_list[i];
DRM_INFO("postdiv1=0x%llx, POSTDIV2=0x%llx\n", postdiv1, postdiv2);
break;
}
}
vco_freq_output = ppll7_freq_divider * pixel_clock_cur;
if (vco_freq_output == 0)
return -EINVAL;
ceil_temp = hdmi_ceil(400000, vco_freq_output);
if (ceil_temp < 0)
return -EINVAL;
refdiv = ((vco_freq_output * ceil_temp) >= 494000) ? 1 : 2;
DRM_DEBUG("refdiv=0x%llx\n", refdiv);
fbdiv = (vco_freq_output * ceil_temp) * refdiv / sys_clock_fref;
DRM_DEBUG("fbdiv=0x%llx\n", fbdiv);
frac = (uint64_t)(ceil_temp * vco_freq_output - sys_clock_fref / refdiv * fbdiv) * refdiv * frac_range;
frac = (uint64_t)frac / sys_clock_fref;
DRM_DEBUG("frac=0x%llx\n", frac);
ppll7ctrl0 = inp32(ctx->pmctrl_base + MIDIA_PPLL7_CTRL0);
ppll7ctrl0 &= ~MIDIA_PPLL7_FREQ_DEVIDER_MASK;
ppll7ctrl0_val = 0x0;
ppll7ctrl0_val |= (uint32_t)(postdiv2 << 23 | postdiv1 << 20 | fbdiv << 8 | refdiv << 2);
ppll7ctrl0_val &= MIDIA_PPLL7_FREQ_DEVIDER_MASK;
ppll7ctrl0 |= ppll7ctrl0_val;
outp32(ctx->pmctrl_base + MIDIA_PPLL7_CTRL0, ppll7ctrl0);
ppll7ctrl1 = inp32(ctx->pmctrl_base + MIDIA_PPLL7_CTRL1);
ppll7ctrl1 &= ~MIDIA_PPLL7_FRAC_MODE_MASK;
ppll7ctrl1_val = 0x0;
ppll7ctrl1_val |= (uint32_t)(1 << 25 | 0 << 24 | frac);
ppll7ctrl1_val &= MIDIA_PPLL7_FRAC_MODE_MASK;
ppll7ctrl1 |= ppll7ctrl1_val;
outp32(ctx->pmctrl_base + MIDIA_PPLL7_CTRL1, ppll7ctrl1);
#if 1
ret = clk_set_rate(ctx->dss_pxl0_clk, 144000000UL);
#else
/*comfirm ldi1 switch ppll7*/
if (pixel_clock_ori <= 255000000)
ret = clk_set_rate(ctx->dss_pxl0_clk, DEFAULT_MIDIA_PPLL7_CLOCK_FREQ/7);
else if (pixel_clock_ori <= 415000000)
ret = clk_set_rate(ctx->dss_pxl0_clk, DEFAULT_MIDIA_PPLL7_CLOCK_FREQ/5);
else if (pixel_clock_ori <= 594000000)
ret = clk_set_rate(ctx->dss_pxl0_clk, DEFAULT_MIDIA_PPLL7_CLOCK_FREQ/3);
else {
DRM_ERROR("Clock don't support!!\n");
return -EINVAL;
}
#endif
if (ret < 0) {
DRM_ERROR("dss_pxl0_clk clk_set_rate(%llu) failed, error=%d!\n",
pixel_clock_cur, ret);
}
return ret;
}
#endif
/*******************************************************************************
**
*/
static void dss_ldi_set_mode(struct dss_crtc *acrtc)
{
int ret;
u32 clk_Hz;
uint64_t clk_Hz;
struct dss_hw_ctx *ctx = acrtc->ctx;
struct drm_display_mode *mode = &acrtc->base.state->mode;
struct drm_display_mode *adj_mode = &acrtc->base.state->adjusted_mode;
DRM_INFO("mode->clock(org) = %u\n", mode->clock);
if(mode->clock == 148500){
clk_Hz = 144000 * 1000UL;
} else if(mode->clock == 83496){
clk_Hz = 80000 * 1000UL;
} else if(mode->clock == 74440){
clk_Hz = 72000 * 1000UL;
} else if(mode->clock == 74250){
clk_Hz = 72000 * 1000UL;
if (acrtc->ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
if (mode->clock == 148500)
clk_Hz = 144000 * 1000UL;
else if (mode->clock == 83496)
clk_Hz = 80000 * 1000UL;
else if (mode->clock == 74440)
clk_Hz = 72000 * 1000UL;
else if (mode->clock == 74250)
clk_Hz = 72000 * 1000UL;
else
clk_Hz = mode->clock * 1000UL;
#ifdef PPLL7_USED_IN_DRV
hdmi_pxl_ppll7_init(ctx, clk_Hz);
#else
/*
* Success should be guaranteed in mode_valid call back,
* so failure shouldn't happen here
*/
ret = clk_set_rate(ctx->dss_pxl0_clk, clk_Hz);
if (ret) {
DRM_ERROR("failed to set pixel clk %dHz (%d)\n", clk_Hz, ret);
}
#endif
adj_mode->clock = clk_Hz / 1000;
} else {
clk_Hz = mode->clock * 1000UL;;
if (mode->clock == 148500)
clk_Hz = 144000 * 1000UL;
else if (mode->clock == 83496)
clk_Hz = 80000 * 1000UL;
else if (mode->clock == 74440)
clk_Hz = 72000 * 1000UL;
else if (mode->clock == 74250)
clk_Hz = 72000 * 1000UL;
else
clk_Hz = mode->clock * 1000UL;
/*
* Success should be guaranteed in mode_valid call back,
* so failure shouldn't happen here
*/
ret = clk_set_rate(ctx->dss_pxl0_clk, clk_Hz);
if (ret) {
DRM_ERROR("failed to set pixel clk %dHz (%d)\n", clk_Hz, ret);
}
adj_mode->clock = clk_get_rate(ctx->dss_pxl0_clk) / 1000;
}
/*
* Success should be guaranteed in mode_valid call back,
* so failure shouldn't happen here
*/
ret = clk_set_rate(ctx->dss_pxl0_clk, clk_Hz);
if (ret) {
DRM_ERROR("failed to set pixel clk %dHz (%d)\n", clk_Hz, ret);
}
adj_mode->clock = clk_get_rate(ctx->dss_pxl0_clk) / 1000;
DRM_INFO("dss_pxl0_clk = %u\n", adj_mode->clock);
DRM_INFO("dss_pxl0_clk [%llu]->[%llu] \n", clk_Hz, clk_get_rate(ctx->dss_pxl0_clk));
dpe_init(acrtc);
}
@@ -135,6 +320,15 @@ static int dss_power_up(struct dss_crtc *acrtc)
int ret;
struct dss_hw_ctx *ctx = acrtc->ctx;
#if defined (CONFIG_HISI_FB_970)
//mds_regulator_enable(ctx);
dpe_common_clk_enable(ctx);
dpe_inner_clk_enable(ctx);
#ifndef DSS_POWER_UP_ON_UEFI
dpe_regulator_enable(ctx);
#endif
dpe_set_clk_rate(ctx);
#else
ret = clk_prepare_enable(ctx->dss_pxl0_clk);
if (ret) {
DRM_ERROR("failed to enable dss_pxl0_clk (%d)\n", ret);
@@ -164,8 +358,11 @@ static int dss_power_up(struct dss_crtc *acrtc)
DRM_ERROR("failed to enable dss_mmbuf_clk (%d)\n", ret);
return ret;
}
dss_inner_clk_pdp_enable(acrtc);
dss_inner_clk_common_enable(acrtc);
#endif
dss_inner_clk_common_enable(ctx);
dss_inner_clk_pdp_enable(ctx);
dpe_interrupt_mask(acrtc);
dpe_interrupt_clear(acrtc);
dpe_irq_enable(acrtc);
@@ -226,17 +423,14 @@ static irqreturn_t dss_irq_handler(int irq, void *data)
isr_s1 = inp32(dss_base + GLB_CPU_PDP_INTS);
isr_s2 = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
isr_s2_dpp = inp32(dss_base + DSS_DPP_OFFSET + DPP_INTS);
isr_s2_smmu = inp32(dss_base + DSS_SMMU_OFFSET + SMMU_INTSTAT_NS);
DRM_INFO_ONCE("isr_s1 = 0x%x!\n", isr_s1);
DRM_INFO_ONCE("isr_s2 = 0x%x!\n", isr_s2);
outp32(dss_base + DSS_SMMU_OFFSET + SMMU_INTCLR_NS, isr_s2_smmu);
outp32(dss_base + DSS_DPP_OFFSET + DPP_INTS, isr_s2_dpp);
outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS, isr_s2);
outp32(dss_base + GLB_CPU_PDP_INTS, isr_s1);
isr_s1 &= ~(inp32(dss_base + GLB_CPU_PDP_INT_MSK));
isr_s2 &= ~(inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK));
isr_s2_dpp &= ~(inp32(dss_base + DSS_DPP_OFFSET + DPP_INT_MSK));
if (isr_s2 & BIT_VACTIVE0_END) {
ctx->vactive0_end_flag++;
@@ -499,45 +693,81 @@ static int dss_dts_parse(struct platform_device *pdev, struct dss_hw_ctx *ctx)
{
struct device *dev = &pdev->dev;
struct device_node *np = NULL;
u32 dss_version_tag;
int ret = 0;
np = of_find_compatible_node(NULL, NULL, DTS_COMP_DSS_NAME);
if (!np) {
DRM_ERROR("NOT FOUND device node %s!\n",
DTS_COMP_DSS_NAME);
return -ENXIO;
DRM_ERROR("NOT FOUND device node %s!\n",
DTS_COMP_DSS_NAME);
return -ENXIO;
}
#if defined (CONFIG_HISI_FB_970)
ret = of_property_read_u32(np, "dss_version_tag", &dss_version_tag);
if (ret) {
DRM_ERROR("failed to get dss_version_tag.\n");
}
ctx->g_dss_version_tag = dss_version_tag;
DRM_INFO("dss_version_tag=0x%x.\n", ctx->g_dss_version_tag);
#else
ctx->g_dss_version_tag = FB_ACCEL_HI366x;
DRM_INFO("dss_version_tag=0x%x.\n", ctx->g_dss_version_tag);
#endif
ctx->base = of_iomap(np, 0);
if (!(ctx->base)) {
DRM_ERROR ("failed to get ade base resource.\n");
return -ENXIO;
DRM_ERROR ("failed to get dss base resource.\n");
return -ENXIO;
}
DRM_INFO("dss base =0x%x.\n", ctx->base);
ctx->peri_crg_base = of_iomap(np, 1);
if (!(ctx->peri_crg_base)) {
DRM_ERROR ("failed to get ade peri_crg_base resource.\n");
return -ENXIO;
DRM_ERROR ("failed to get dss peri_crg_base resource.\n");
return -ENXIO;
}
ctx->sctrl_base = of_iomap(np, 2);
if (!(ctx->sctrl_base)) {
DRM_ERROR ("failed to get ade sctrl_base resource.\n");
return -ENXIO;
DRM_ERROR ("failed to get dss sctrl_base resource.\n");
return -ENXIO;
}
ctx->pmc_base = of_iomap(np, 3);
if (!(ctx->pmc_base)) {
DRM_ERROR ("failed to get ade pmc_base resource.\n");
if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
ctx->pctrl_base = of_iomap(np, 3);
if (!(ctx->pctrl_base)) {
DRM_ERROR ("failed to get dss pctrl_base resource.\n");
return -ENXIO;
}
} else {
ctx->pmc_base = of_iomap(np, 3);
if (!(ctx->pmc_base)) {
DRM_ERROR ("failed to get dss pmc_base resource.\n");
return -ENXIO;
}
}
ctx->noc_dss_base = of_iomap(np, 4);
if (!(ctx->noc_dss_base)) {
DRM_ERROR ("failed to get noc_dss_base resource.\n");
return -ENXIO;
DRM_ERROR ("failed to get noc_dss_base resource.\n");
return -ENXIO;
}
#if defined (CONFIG_HISI_FB_970)
ctx->pmctrl_base = of_iomap(np, 5);
if (!(ctx->pmctrl_base)) {
DRM_ERROR ("failed to get dss pmctrl_base resource.\n");
return -ENXIO;
}
ctx->media_crg_base = of_iomap(np, 6);
if (!(ctx->media_crg_base)) {
DRM_ERROR ("failed to get dss media_crg_base resource.\n");
return -ENXIO;
}
#endif
/* get irq no */
ctx->irq = irq_of_parse_and_map(np, 0);
if (ctx->irq <= 0) {
@@ -545,12 +775,22 @@ static int dss_dts_parse(struct platform_device *pdev, struct dss_hw_ctx *ctx)
return -ENXIO;
}
DRM_INFO("dss irq = %d.", ctx->irq);
DRM_INFO("dss irq = %d. \n", ctx->irq);
#ifndef DSS_POWER_UP_ON_UEFI
#if defined (CONFIG_HISI_FB_970)
ctx->dpe_regulator = devm_regulator_get(dev, REGULATOR_PDP_NAME);
if (!ctx->dpe_regulator) {
DRM_ERROR("failed to get regulator resource! ret=%d.\n", ret);
return -ENXIO;
}
#endif
#endif
ctx->dss_mmbuf_clk = devm_clk_get(dev, "clk_dss_axi_mm");
if (!ctx->dss_mmbuf_clk) {
DRM_ERROR("failed to parse dss_mmbuf_clk\n");
return -ENODEV;
return -ENODEV;
}
ctx->dss_axi_clk = devm_clk_get(dev, "aclk_dss");
@@ -562,7 +802,7 @@ static int dss_dts_parse(struct platform_device *pdev, struct dss_hw_ctx *ctx)
ctx->dss_pclk_dss_clk = devm_clk_get(dev, "pclk_dss");
if (!ctx->dss_pclk_dss_clk) {
DRM_ERROR("failed to parse dss_pclk_dss_clk\n");
return -ENODEV;
return -ENODEV;
}
ctx->dss_pri_clk = devm_clk_get(dev, "clk_edc0");
@@ -571,15 +811,17 @@ static int dss_dts_parse(struct platform_device *pdev, struct dss_hw_ctx *ctx)
return -ENODEV;
}
ret = clk_set_rate(ctx->dss_pri_clk, DEFAULT_DSS_CORE_CLK_07V_RATE);
if (ret < 0) {
DRM_ERROR("dss_pri_clk clk_set_rate(%lu) failed, error=%d!\n",
DEFAULT_DSS_CORE_CLK_07V_RATE, ret);
return -EINVAL;
}
if (ctx->g_dss_version_tag != FB_ACCEL_KIRIN970) {
ret = clk_set_rate(ctx->dss_pri_clk, DEFAULT_DSS_CORE_CLK_07V_RATE);
if (ret < 0) {
DRM_ERROR("dss_pri_clk clk_set_rate(%lu) failed, error=%d!\n",
DEFAULT_DSS_CORE_CLK_07V_RATE, ret);
return -EINVAL;
}
DRM_INFO("dss_pri_clk:[%lu]->[%llu].\n",
DEFAULT_DSS_CORE_CLK_07V_RATE, (uint64_t)clk_get_rate(ctx->dss_pri_clk));
DRM_INFO("dss_pri_clk:[%lu]->[%llu].\n",
DEFAULT_DSS_CORE_CLK_07V_RATE, (uint64_t)clk_get_rate(ctx->dss_pri_clk));
}
ctx->dss_pxl0_clk = devm_clk_get(dev, "clk_ldi0");
if (!ctx->dss_pxl0_clk) {
@@ -587,18 +829,19 @@ static int dss_dts_parse(struct platform_device *pdev, struct dss_hw_ctx *ctx)
return -ENODEV;
}
ret = clk_set_rate(ctx->dss_pxl0_clk, DSS_MAX_PXL0_CLK_144M);
if (ret < 0) {
DRM_ERROR("dss_pxl0_clk clk_set_rate(%lu) failed, error=%d!\n",
DSS_MAX_PXL0_CLK_144M, ret);
return -EINVAL;
if (ctx->g_dss_version_tag != FB_ACCEL_KIRIN970) {
ret = clk_set_rate(ctx->dss_pxl0_clk, DSS_MAX_PXL0_CLK_144M);
if (ret < 0) {
DRM_ERROR("dss_pxl0_clk clk_set_rate(%lu) failed, error=%d!\n",
DSS_MAX_PXL0_CLK_144M, ret);
return -EINVAL;
}
DRM_INFO("dss_pxl0_clk:[%lu]->[%llu].\n",
DSS_MAX_PXL0_CLK_144M, (uint64_t)clk_get_rate(ctx->dss_pxl0_clk));
}
DRM_INFO("dss_pxl0_clk:[%lu]->[%llu].\n",
DSS_MAX_PXL0_CLK_144M, (uint64_t)clk_get_rate(ctx->dss_pxl0_clk));
/* regulator enable */
dss_enable_iommu(pdev, ctx);
return 0;
@@ -668,7 +911,7 @@ static int dss_drm_init(struct drm_device *dev)
ret = devm_request_irq(dev->dev, ctx->irq, dss_irq_handler,
IRQF_SHARED, dev->driver->name, acrtc);
if (ret) {
DRM_ERROR("fail to devm_request_irq, ret=%d!", ret);
DRM_ERROR("fail to devm_request_irq, ret=%d!", ret);
return ret;
}
+448 -39
View File
@@ -30,15 +30,344 @@
#define DSS_CHN_MAX_DEFINE (DSS_COPYBIT_MAX)
static int mid_array[DSS_CHN_MAX_DEFINE] = {0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x2, 0x1, 0x3, 0x0};
#if defined (CONFIG_HISI_FB_970)
uint32_t g_dss_module_base[DSS_CHN_MAX_DEFINE][MODULE_CHN_MAX] = {
// D0
{
MIF_CH0_OFFSET, //MODULE_MIF_CHN
AIF0_CH0_OFFSET, //MODULE_AIF0_CHN
AIF1_CH0_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_RCH0, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_OV_OEN, //MODULE_MCTL_CHN_OV_OEN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_STARTY, //MODULE_MCTL_CHN_STARTY
DSS_MCTRL_SYS_OFFSET + MCTL_MOD0_DBG, //MODULE_MCTL_CHN_MOD_DBG
DSS_RCH_D0_DMA_OFFSET, //MODULE_DMA
DSS_RCH_D0_DFC_OFFSET, //MODULE_DFC
0, //MODULE_SCL
0, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
0, //MODULE_POST_CLIP_ES
0, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_RCH_D0_CSC_OFFSET, //MODULE_CSC
},
// D1
{
MIF_CH1_OFFSET, //MODULE_MIF_CHN
AIF0_CH1_OFFSET, //MODULE_AIF0_CHN
AIF1_CH1_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_RCH1, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_RCH1_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH1_OV_OEN, //MODULE_MCTL_CHN_OV_OEN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH1_STARTY, //MODULE_MCTL_CHN_STARTY
DSS_MCTRL_SYS_OFFSET + MCTL_MOD1_DBG, //MODULE_MCTL_CHN_MOD_DBG
DSS_RCH_D1_DMA_OFFSET, //MODULE_DMA
DSS_RCH_D1_DFC_OFFSET, //MODULE_DFC
0, //MODULE_SCL
0, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
0, //MODULE_POST_CLIP_ES
0, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_RCH_D1_CSC_OFFSET, //MODULE_CSC
},
// V0
{
MIF_CH2_OFFSET, //MODULE_MIF_CHN
AIF0_CH2_OFFSET, //MODULE_AIF0_CHN
AIF1_CH2_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_RCH2, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_RCH2_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH2_OV_OEN, //MODULE_MCTL_CHN_OV_OEN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH2_STARTY, //MODULE_MCTL_CHN_STARTY
DSS_MCTRL_SYS_OFFSET + MCTL_MOD2_DBG, //MODULE_MCTL_CHN_MOD_DBG
DSS_RCH_VG0_DMA_OFFSET, //MODULE_DMA
DSS_RCH_VG0_DFC_OFFSET, //MODULE_DFC
DSS_RCH_VG0_SCL_OFFSET, //MODULE_SCL
DSS_RCH_VG0_SCL_LUT_OFFSET, //MODULE_SCL_LUT
DSS_RCH_VG0_ARSR_OFFSET, //MODULE_ARSR2P
DSS_RCH_VG0_ARSR_LUT_OFFSET, //MODULE_ARSR2P_LUT
DSS_RCH_VG0_POST_CLIP_OFFSET_ES, //MODULE_POST_CLIP_ES
DSS_RCH_VG0_POST_CLIP_OFFSET, //MODULE_POST_CLIP
DSS_RCH_VG0_PCSC_OFFSET, //MODULE_PCSC
DSS_RCH_VG0_CSC_OFFSET, //MODULE_CSC
},
// G0
{
MIF_CH3_OFFSET, //MODULE_MIF_CHN
AIF0_CH3_OFFSET, //MODULE_AIF0_CHN
AIF1_CH3_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_RCH3, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_RCH3_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH3_OV_OEN, //MODULE_MCTL_CHN_OV_OEN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH3_STARTY, //MODULE_MCTL_CHN_STARTY
DSS_MCTRL_SYS_OFFSET + MCTL_MOD3_DBG, //MODULE_MCTL_CHN_MOD_DBG
DSS_RCH_G0_DMA_OFFSET, //MODULE_DMA
DSS_RCH_G0_DFC_OFFSET, //MODULE_DFC
DSS_RCH_G0_SCL_OFFSET, //MODULE_SCL
0, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
DSS_RCH_G0_POST_CLIP_OFFSET_ES, //MODULE_POST_CLIP_ES
DSS_RCH_G0_POST_CLIP_OFFSET, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_RCH_G0_CSC_OFFSET, //MODULE_CSC
},
// V1
{
MIF_CH4_OFFSET, //MODULE_MIF_CHN
AIF0_CH4_OFFSET, //MODULE_AIF0_CHN
AIF1_CH4_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_RCH4, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_RCH4_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH4_OV_OEN, //MODULE_MCTL_CHN_OV_OEN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH4_STARTY, //MODULE_MCTL_CHN_STARTY
DSS_MCTRL_SYS_OFFSET + MCTL_MOD4_DBG, //MODULE_MCTL_CHN_MOD_DBG
DSS_RCH_VG1_DMA_OFFSET, //MODULE_DMA
DSS_RCH_VG1_DFC_OFFSET, //MODULE_DFC
DSS_RCH_VG1_SCL_OFFSET, //MODULE_SCL
DSS_RCH_VG1_SCL_LUT_OFFSET, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
DSS_RCH_VG1_POST_CLIP_OFFSET_ES, //MODULE_POST_CLIP_ES
DSS_RCH_VG1_POST_CLIP_OFFSET, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_RCH_VG1_CSC_OFFSET, //MODULE_CSC
},
// G1
{
MIF_CH5_OFFSET, //MODULE_MIF_CHN
AIF0_CH5_OFFSET, //MODULE_AIF0_CHN
AIF1_CH5_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_RCH5, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_RCH5_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH5_OV_OEN, //MODULE_MCTL_CHN_OV_OEN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH5_STARTY, //MODULE_MCTL_CHN_STARTY
DSS_MCTRL_SYS_OFFSET + MCTL_MOD5_DBG, //MODULE_MCTL_CHN_MOD_DBG
DSS_RCH_G1_DMA_OFFSET, //MODULE_DMA
DSS_RCH_G1_DFC_OFFSET, //MODULE_DFC
DSS_RCH_G1_SCL_OFFSET, //MODULE_SCL
0, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
DSS_RCH_G1_POST_CLIP_OFFSET_ES, //MODULE_POST_CLIP_ES
DSS_RCH_G1_POST_CLIP_OFFSET, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_RCH_G1_CSC_OFFSET, //MODULE_CSC
},
// D2
{
MIF_CH6_OFFSET, //MODULE_MIF_CHN
AIF0_CH6_OFFSET, //MODULE_AIF0_CHN
AIF1_CH6_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_RCH6, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_RCH6_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH6_OV_OEN, //MODULE_MCTL_CHN_OV_OEN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH6_STARTY, //MODULE_MCTL_CHN_STARTY
DSS_MCTRL_SYS_OFFSET + MCTL_MOD6_DBG, //MODULE_MCTL_CHN_MOD_DBG
DSS_RCH_D2_DMA_OFFSET, //MODULE_DMA
DSS_RCH_D2_DFC_OFFSET, //MODULE_DFC
0, //MODULE_SCL
0, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
0, //MODULE_POST_CLIP_ES
0, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_RCH_D2_CSC_OFFSET, //MODULE_CSC
},
// D3
{
MIF_CH7_OFFSET, //MODULE_MIF_CHN
AIF0_CH7_OFFSET, //MODULE_AIF0_CHN
AIF1_CH7_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_RCH7, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_RCH7_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH7_OV_OEN, //MODULE_MCTL_CHN_OV_OEN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH7_STARTY, //MODULE_MCTL_CHN_STARTY
DSS_MCTRL_SYS_OFFSET + MCTL_MOD7_DBG, //MODULE_MCTL_CHN_MOD_DBG
DSS_RCH_D3_DMA_OFFSET, //MODULE_DMA
DSS_RCH_D3_DFC_OFFSET, //MODULE_DFC
0, //MODULE_SCL
0, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
0, //MODULE_POST_CLIP_ES
0, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_RCH_D3_CSC_OFFSET, //MODULE_CSC
},
// W0
{
MIF_CH8_OFFSET, //MODULE_MIF_CHN
AIF0_CH8_OFFSET, //MODULE_AIF0_CHN
AIF1_CH8_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_WCH0, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_WCH0_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_WCH0_OV_IEN, //MODULE_MCTL_CHN_OV_OEN
0, //MODULE_MCTL_CHN_STARTY
0, //MODULE_MCTL_CHN_MOD_DBG
DSS_WCH0_DMA_OFFSET, //MODULE_DMA
DSS_WCH0_DFC_OFFSET, //MODULE_DFC
0, //MODULE_SCL
0, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
0, //MODULE_POST_CLIP_ES
0, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_WCH0_CSC_OFFSET, //MODULE_CSC
},
// W1
{
MIF_CH9_OFFSET, //MODULE_MIF_CHN
AIF0_CH9_OFFSET, //MODULE_AIF0_CHN
AIF1_CH9_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_WCH1, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_WCH1_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_WCH1_OV_IEN, //MODULE_MCTL_CHN_OV_OEN
0, //MODULE_MCTL_CHN_STARTY
0, //MODULE_MCTL_CHN_MOD_DBG
DSS_WCH1_DMA_OFFSET, //MODULE_DMA
DSS_WCH1_DFC_OFFSET, //MODULE_DFC
0, //MODULE_SCL
0, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
0, //MODULE_POST_CLIP_ES
0, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_WCH1_CSC_OFFSET, //MODULE_CSC
},
// V2
{
MIF_CH10_OFFSET, //MODULE_MIF_CHN
AIF0_CH11_OFFSET, //MODULE_AIF0_CHN
AIF1_CH11_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_RCH8, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_RCH8_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
DSS_MCTRL_SYS_OFFSET + MCTL_RCH8_OV_OEN, //MODULE_MCTL_CHN_OV_OEN
0, //MODULE_MCTL_CHN_STARTY
DSS_MCTRL_SYS_OFFSET + MCTL_MOD8_DBG, //MODULE_MCTL_CHN_MOD_DBG
DSS_RCH_VG2_DMA_OFFSET, //MODULE_DMA
DSS_RCH_VG2_DFC_OFFSET, //MODULE_DFC
DSS_RCH_VG2_SCL_OFFSET, //MODULE_SCL
DSS_RCH_VG2_SCL_LUT_OFFSET, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
DSS_RCH_VG2_POST_CLIP_OFFSET_ES, //MODULE_POST_CLIP_ES
DSS_RCH_VG2_POST_CLIP_OFFSET, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_RCH_VG2_CSC_OFFSET, //MODULE_CSC
},
// W2
{
MIF_CH11_OFFSET, //MODULE_MIF_CHN
AIF0_CH12_OFFSET, //MODULE_AIF0_CHN
AIF1_CH12_OFFSET, //MODULE_AIF1_CHN
MCTL_CTL_MUTEX_WCH2, //MODULE_MCTL_CHN_MUTEX
DSS_MCTRL_SYS_OFFSET + MCTL_WCH2_FLUSH_EN, //MODULE_MCTL_CHN_FLUSH_EN
0, //MODULE_MCTL_CHN_OV_OEN
0, //MODULE_MCTL_CHN_STARTY
0, //MODULE_MCTL_CHN_MOD_DBG
DSS_WCH2_DMA_OFFSET, //MODULE_DMA
DSS_WCH2_DFC_OFFSET, //MODULE_DFC
0, //MODULE_SCL
0, //MODULE_SCL_LUT
0, //MODULE_ARSR2P
0, //MODULE_ARSR2P_LUT
0, //MODULE_POST_CLIP_ES
0, //MODULE_POST_CLIP
0, //MODULE_PCSC
DSS_WCH2_CSC_OFFSET, //MODULE_CSC
},
};
uint32_t g_dss_module_ovl_base[DSS_MCTL_IDX_MAX][MODULE_OVL_MAX] = {
{DSS_OVL0_OFFSET,
DSS_MCTRL_CTL0_OFFSET},
{DSS_OVL1_OFFSET,
DSS_MCTRL_CTL1_OFFSET},
{DSS_OVL2_OFFSET,
DSS_MCTRL_CTL2_OFFSET},
{DSS_OVL3_OFFSET,
DSS_MCTRL_CTL3_OFFSET},
{0,
DSS_MCTRL_CTL4_OFFSET},
{0,
DSS_MCTRL_CTL5_OFFSET},
};
//SCF_LUT_CHN coef_idx
int g_scf_lut_chn_coef_idx[DSS_CHN_MAX_DEFINE] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
uint32_t g_dss_module_cap[DSS_CHN_MAX_DEFINE][MODULE_CAP_MAX] = {
/* D2 */
{0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1},
/* D3 */
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},
/* V0 */
{0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1},
/* G0 */
{0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0},
/* V1 */
{0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1},
/* G1 */
{0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0},
/* D0 */
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},
/* D1 */
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},
/* W0 */
{1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1},
/* W1 */
{1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1},
/* V2 */
{0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1},
/* W2 */
{1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1},
};
/* number of smrx idx for each channel */
uint32_t g_dss_chn_sid_num[DSS_CHN_MAX_DEFINE] = {
4, 1, 4, 4, 4, 4, 1, 1, 3, 4, 3, 3
};
/* start idx of each channel */
/* smrx_idx = g_dss_smmu_smrx_idx[chn_idx] + (0 ~ g_dss_chn_sid_num[chn_idx]) */
uint32_t g_dss_smmu_smrx_idx[DSS_CHN_MAX_DEFINE] = {
0, 4, 5, 9, 13, 17, 21, 22, 26, 29, 23, 36
};
#else
/*
** dss_chn_idx
** DSS_RCHN_D2 = 0, DSS_RCHN_D3, DSS_RCHN_V0, DSS_RCHN_G0, DSS_RCHN_V1,
** DSS_RCHN_G1, DSS_RCHN_D0, DSS_RCHN_D1, DSS_WCHN_W0, DSS_WCHN_W1,
** DSS_RCHN_V2, DSS_WCHN_W2,
*/
/*lint -e785*/
u32 g_dss_module_base[DSS_CHN_MAX_DEFINE][MODULE_CHN_MAX] = {
/* D0 */
{
@@ -291,7 +620,6 @@ u32 g_dss_module_base[DSS_CHN_MAX_DEFINE][MODULE_CHN_MAX] = {
},
};
/*lint +e785*/
u32 g_dss_module_ovl_base[DSS_MCTL_IDX_MAX][MODULE_OVL_MAX] = {
{DSS_OVL0_OFFSET,
DSS_MCTRL_CTL0_OFFSET},
@@ -357,7 +685,7 @@ u32 g_dss_smmu_smrx_idx[DSS_CHN_MAX_DEFINE] = {
u32 g_dss_mif_sid_map[DSS_CHN_MAX] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#endif
static int hisi_pixel_format_hal2dma(int format)
{
int ret = 0;
@@ -555,10 +883,12 @@ static int hisi_dss_smmu_config(struct dss_hw_ctx *ctx, int chn_idx, bool mmu_en
for (i = 0; i < g_dss_chn_sid_num[chn_idx]; i++) {
idx = g_dss_smmu_smrx_idx[chn_idx] + i;
if (!mmu_enable)
if (!mmu_enable) {
set_reg(smmu_base + SMMU_SMRx_NS + idx * 0x4, 1, 32, 0);
else
set_reg(smmu_base + SMMU_SMRx_NS + idx * 0x4, 0x70, 32, 0);
} else {
//set_reg(smmu_base + SMMU_SMRx_NS + idx * 0x4, 0x70, 32, 0);
set_reg(smmu_base + SMMU_SMRx_NS + idx * 0x4, 0x1C, 32, 0);
}
}
return 0;
@@ -668,7 +998,11 @@ static int hisi_dss_mctl_sys_config(struct dss_hw_ctx *ctx, int chn_idx)
set_reg(mctl_sys_base + mctl_rch_ov_oen_offset,
((1 << (layer_idx + 1)) | (0x100 << DSS_OVL0)), 32, 0);
set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0x8, 4, 0);
if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0xe, 4, 0);
} else {
set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0x8, 4, 0);
}
set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, chn_idx, 4, (layer_idx + 1) * 4);
@@ -805,8 +1139,10 @@ static int hisi_dss_rdma_config(struct dss_hw_ctx *ctx,
set_reg(rdma_base + DMA_OFT_Y0, rdma_oft_y0, 16, 0);
set_reg(rdma_base + DMA_OFT_X1, rdma_oft_x1, 12, 0);
set_reg(rdma_base + DMA_OFT_Y1, rdma_oft_y1, 16, 0);
set_reg(rdma_base + DMA_CTRL, rdma_format, 5, 3);
set_reg(rdma_base + DMA_CTRL, (mmu_enable ? 0x1 : 0x0), 1, 8);
//set_reg(rdma_base + DMA_CTRL, rdma_format, 5, 3);
//set_reg(rdma_base + DMA_CTRL, (mmu_enable ? 0x1 : 0x0), 1, 8);
set_reg(rdma_base + DMA_CTRL, 0x130, 32, 0);
//set_reg(rdma_base + DMA_CTRL, (mmu_enable ? 0x1 : 0x0), 1, 8);
set_reg(rdma_base + DMA_STRETCH_SIZE_VRT, stretch_size_vrt, 32, 0);
set_reg(rdma_base + DMA_DATA_ADDR0, display_addr, 32, 0);
set_reg(rdma_base + DMA_STRIDE0, rdma_stride, 13, 0);
@@ -866,32 +1202,54 @@ int hisi_dss_ovl_base_config(struct dss_hw_ctx *ctx, u32 xres, u32 yres)
return -1;
}
DRM_INFO("+. \n");
mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
mctl_base = ctx->base +
g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE];
ovl0_base = ctx->base +
g_dss_module_ovl_base[DSS_OVL0][MODULE_OVL_BASE];
set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x1, 32, 0);
set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x0, 32, 0);
if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
set_reg(ovl0_base + OV8_REG_DEFAULT, 0x1, 32, 0);
set_reg(ovl0_base + OV8_REG_DEFAULT, 0x0, 32, 0);
set_reg(ovl0_base + OVL_SIZE, (xres - 1) |
((yres - 1) << 16), 32, 0);
set_reg(ovl0_base + OVL_SIZE, (xres - 1) | ((yres - 1) << 16), 32, 0);
#ifdef CONFIG_HISI_FB_OV_BASE_USED
set_reg(ovl0_base + OVL_BG_COLOR, 0xFFFF0000, 32, 0);
DRM_INFO("CONFIG_HISI_FB_OV_BASE_USED !!. \n");
set_reg(ovl0_base + OV_BG_COLOR_RGB, 0x3FF00000, 32, 0);
set_reg(ovl0_base + OV_BG_COLOR_A, 0x3FF, 32, 0);
#else
set_reg(ovl0_base + OVL_BG_COLOR, 0xFF000000, 32, 0);
set_reg(ovl0_base + OV_BG_COLOR_RGB, 0x00000000, 32, 0);
set_reg(ovl0_base + OV_BG_COLOR_A, 0x00000000, 32, 0);
#endif
set_reg(ovl0_base + OVL_DST_STARTPOS, 0x0, 32, 0);
set_reg(ovl0_base + OVL_DST_ENDPOS, (xres - 1) | ((yres - 1) << 16), 32, 0);
set_reg(ovl0_base + OVL_GCFG, 0x10001, 32, 0);
set_reg(ovl0_base + OV_DST_STARTPOS, 0x0, 32, 0);
set_reg(ovl0_base + OV_DST_ENDPOS, (xres - 1) |
((yres - 1) << 16), 32, 0);
set_reg(ovl0_base + OV_GCFG, 0x10001, 32, 0);
set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0xE, 4, 0);
} else {
set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x1, 32, 0);
set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x0, 32, 0);
set_reg(ovl0_base + OVL_SIZE, (xres - 1) | ((yres - 1) << 16), 32, 0);
#ifdef CONFIG_HISI_FB_OV_BASE_USED
set_reg(ovl0_base + OVL_BG_COLOR, 0xFFFF0000, 32, 0);
#else
set_reg(ovl0_base + OVL_BG_COLOR, 0xFF000000, 32, 0);
#endif
set_reg(ovl0_base + OVL_DST_STARTPOS, 0x0, 32, 0);
set_reg(ovl0_base + OVL_DST_ENDPOS, (xres - 1) | ((yres - 1) << 16), 32, 0);
set_reg(ovl0_base + OVL_GCFG, 0x10001, 32, 0);
set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0x8, 4, 0);
}
set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 32, 0);
set_reg(mctl_base + MCTL_CTL_MUTEX_DBUF, 0x1, 2, 0);
set_reg(mctl_base + MCTL_CTL_MUTEX_OV, 1 << DSS_OVL0, 4, 0);
set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0x8, 4, 0);
set_reg(mctl_sys_base + MCTL_OV0_FLUSH_EN, 0xd, 4, 0);
DRM_INFO("-. \n");
return 0;
}
@@ -908,21 +1266,43 @@ static int hisi_dss_ovl_config(struct dss_hw_ctx *ctx,
ovl0_base = ctx->base +
g_dss_module_ovl_base[DSS_OVL0][MODULE_OVL_BASE];
set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x1, 32, 0);
set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x0, 32, 0);
set_reg(ovl0_base + OVL_SIZE, (xres - 1) |
((yres - 1) << 16), 32, 0);
set_reg(ovl0_base + OVL_BG_COLOR, 0xFF000000, 32, 0);
set_reg(ovl0_base + OVL_DST_STARTPOS, 0x0, 32, 0);
set_reg(ovl0_base + OVL_DST_ENDPOS, (xres - 1) |
((yres - 1) << 16), 32, 0);
set_reg(ovl0_base + OVL_GCFG, 0x10001, 32, 0);
set_reg(ovl0_base + OVL_LAYER0_POS, (rect->left) |
((rect->top) << 16), 32, 0);
set_reg(ovl0_base + OVL_LAYER0_SIZE, (rect->right) |
((rect->bottom) << 16), 32, 0);
set_reg(ovl0_base + OVL_LAYER0_ALPHA, 0x00ff40ff, 32, 0);
set_reg(ovl0_base + OVL_LAYER0_CFG, 0x1, 1, 0);
if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
set_reg(ovl0_base + OV8_REG_DEFAULT, 0x1, 32, 0);
set_reg(ovl0_base + OV8_REG_DEFAULT, 0x0, 32, 0);
set_reg(ovl0_base + OVL_SIZE, (xres - 1) |
((yres - 1) << 16), 32, 0);
set_reg(ovl0_base + OV_BG_COLOR_RGB, 0x3FF00000, 32, 0);
set_reg(ovl0_base + OV_BG_COLOR_A, 0x3ff, 32, 0);
set_reg(ovl0_base + OV_DST_STARTPOS, 0x0, 32, 0);
set_reg(ovl0_base + OV_DST_ENDPOS, (xres - 1) |
((yres - 1) << 16), 32, 0);
set_reg(ovl0_base + OV_GCFG, 0x10001, 32, 0);
set_reg(ovl0_base + OV_LAYER0_POS, (rect->left) |
((rect->top) << 16), 32, 0);
set_reg(ovl0_base + OV_LAYER0_SIZE, (rect->right) |
((rect->bottom) << 16), 32, 0);
set_reg(ovl0_base + OV_LAYER0_ALPHA_MODE, 0x1004000, 32, 0);///NEED CHECK??
//set_reg(ovl0_base + OV_LAYER0_ALPHA_A, 0x3fc03fc, 32, 0);
set_reg(ovl0_base + OV_LAYER0_ALPHA_A, 0x3ff03ff, 32, 0);
set_reg(ovl0_base + OV_LAYER0_CFG, 0x1, 1, 0);
} else {
set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x1, 32, 0);
set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x0, 32, 0);
set_reg(ovl0_base + OVL_SIZE, (xres - 1) |
((yres - 1) << 16), 32, 0);
set_reg(ovl0_base + OVL_BG_COLOR, 0xFFFF0000, 32, 0);
set_reg(ovl0_base + OVL_DST_STARTPOS, 0x0, 32, 0);
set_reg(ovl0_base + OVL_DST_ENDPOS, (xres - 1) |
((yres - 1) << 16), 32, 0);
set_reg(ovl0_base + OVL_GCFG, 0x10001, 32, 0);
set_reg(ovl0_base + OVL_LAYER0_POS, (rect->left) |
((rect->top) << 16), 32, 0);
set_reg(ovl0_base + OVL_LAYER0_SIZE, (rect->right) |
((rect->bottom) << 16), 32, 0);
set_reg(ovl0_base + OVL_LAYER0_ALPHA, 0x00ff40ff, 32, 0);
set_reg(ovl0_base + OVL_LAYER0_CFG, 0x1, 1, 0);
}
return 0;
}
@@ -978,13 +1358,18 @@ void hisi_dss_smmu_on(struct dss_hw_ctx *ctx)
void __iomem *smmu_base;
struct iommu_domain_data *domain_data = NULL;
uint32_t phy_pgd_base = 0;
uint64_t fama_phy_pgd_base;
uint32_t fama_ptw_msb;
DRM_INFO("+. \n");
if (!ctx) {
DRM_ERROR("ctx is NULL!\n");
return;
}
DRM_INFO("ctx->base = 0x%x \n", ctx->base);
smmu_base = ctx->base + DSS_SMMU_OFFSET;
DRM_INFO("smmu_base = 0x%x \n", smmu_base);
set_reg(smmu_base + SMMU_SCR, 0x0, 1, 0); /*global bypass cancel*/
set_reg(smmu_base + SMMU_SCR, 0x1, 8, 20); /*ptw_mid*/
@@ -1009,8 +1394,12 @@ void hisi_dss_smmu_on(struct dss_hw_ctx *ctx)
/*TTBR0*/
domain_data = (struct iommu_domain_data *)(ctx->mmu_domain->priv);
fama_phy_pgd_base = domain_data->phy_pgd_base;
phy_pgd_base = (uint32_t)(domain_data->phy_pgd_base);
DRM_DEBUG("fama_phy_pgd_base = %llu, phy_pgd_base =0x%x \n", fama_phy_pgd_base, phy_pgd_base);
set_reg(smmu_base + SMMU_CB_TTBR0, phy_pgd_base, 32, 0);
DRM_INFO("-. \n");
}
void hisifb_dss_on(struct dss_hw_ctx *ctx)
@@ -1105,8 +1494,12 @@ void hisi_fb_pan_display(struct drm_plane *plane)
struct dss_crtc *acrtc = aplane->acrtc;
struct dss_hw_ctx *ctx = acrtc->ctx;
#ifndef CMA_BUFFER_USED
struct kirin_drm_private *priv = plane->dev->dev_private;
struct kirin_fbdev *fbdev = to_kirin_fbdev(priv->fbdev);
#else
struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(state->fb, 0);
#endif
bool afbcd = false;
bool mmu_enable = true;
@@ -1116,6 +1509,7 @@ void hisi_fb_pan_display(struct drm_plane *plane)
u32 display_addr = 0;
u32 hal_fmt;
int chn_idx = DSS_RCHN_D2;
char filename[256] = {0};
int crtc_x = state->crtc_x;
int crtc_y = state->crtc_y;
@@ -1134,16 +1528,24 @@ void hisi_fb_pan_display(struct drm_plane *plane)
bpp = fb->bits_per_pixel / 8;
stride = fb->pitches[0];
#if defined(CONFIG_HISI_FB_LDI_COLORBAR_USED) || defined(CONFIG_HISI_FB_DPP_COLORBAR_USED) || defined(CONFIG_HISI_FB_OV_BASE_USED)
return;
#endif
#ifndef CMA_BUFFER_USED
if (fbdev)
display_addr = (u32)fbdev->smem_start + src_y * stride;
else
printk("JDB: fbdev is null?\n");
DRM_ERROR("fbdev is null? \n");
#else
display_addr = (u32)obj->paddr + src_y * stride;
#endif
rect.left = 0;
rect.right = src_w - 1;
rect.top = 0;
rect.bottom = src_h - 1;
hal_fmt = dss_get_format(fb->pixel_format);
hal_fmt = HISI_FB_PIXEL_FORMAT_BGRA_8888;//dss_get_format(fb->pixel_format);
DRM_DEBUG("channel%d: src:(%d,%d, %dx%d) crtc:(%d,%d, %dx%d), rect(%d,%d,%d,%d),"
"fb:%dx%d, pixel_format=%d, stride=%d, paddr=0x%x, bpp=%d, bits_per_pixel=%d.\n",
@@ -1178,7 +1580,7 @@ void hisi_fb_pan_display(struct drm_plane *plane)
hisi_dss_wait_for_complete(ctx);
}
void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer)
void hisi_dss_online_play(struct kirin_fbdev *fbdev, struct drm_plane *plane, drm_dss_layer_t *layer)
{
struct drm_plane_state *state = plane->state;
struct drm_display_mode *mode;
@@ -1207,14 +1609,21 @@ void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer)
bpp = layer->img.bpp;
stride = layer->img.stride;
display_addr = layer->img.vir_addr;
hal_fmt = layer->img.format;
hal_fmt = HISI_FB_PIXEL_FORMAT_RGBA_8888;//layer->img.format;
rect.left = 0;
rect.right = src_w - 1;
rect.top = 0;
rect.bottom = src_h - 1;
DRM_DEBUG("channel%d: src:(%dx%d) rect(%d,%d,%d,%d),"
"pixel_format=%d, stride=%d, paddr=0x%x, bpp=%d.\n",
chn_idx, src_w, src_h,
rect.left, rect.top, rect.right, rect.bottom,
hal_fmt, stride, display_addr, bpp);
hfp = mode->hsync_start - mode->hdisplay;
hbp = mode->htotal - mode->hsync_end;
hsw = mode->hsync_end - mode->hsync_start;
@@ -1229,7 +1638,7 @@ void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer)
hisi_dss_rdma_config(ctx, &rect, display_addr, hal_fmt, bpp, chn_idx, afbcd, mmu_enable);
hisi_dss_rdfc_config(ctx, &rect, hal_fmt, bpp, chn_idx);
hisi_dss_ovl_config(ctx, &rect, mode->hdisplay, mode->vdisplay);
hisi_dss_ovl_config(ctx, &rect, src_w, src_h);
hisi_dss_mctl_ov_config(ctx, chn_idx);
hisi_dss_mctl_sys_config(ctx, chn_idx);
@@ -83,7 +83,7 @@ struct drm_framebuffer *kirin_framebuffer_init(struct drm_device *dev,
goto fail;
}
DRM_DEBUG("create: FB ID: %d (%p)", fb->base.id, fb);
DRM_DEBUG("create: FB ID: %d (%p) \n", fb->base.id, fb);
return fb;
@@ -0,0 +1,197 @@
/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* 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 KIRIN_FB_PANEL_H
#define KIRIN_FB_PANEL_H
/* dts initial */
#define DTS_FB_RESOURCE_INIT_READY BIT(0)
#define DTS_PWM_READY BIT(1)
/* #define DTS_BLPWM_READY BIT(2) */
#define DTS_SPI_READY BIT(3)
#define DTS_PANEL_PRIMARY_READY BIT(4)
#define DTS_PANEL_EXTERNAL_READY BIT(5)
#define DTS_PANEL_OFFLINECOMPOSER_READY BIT(6)
#define DTS_PANEL_WRITEBACK_READY BIT(7)
#define DTS_PANEL_MEDIACOMMON_READY BIT(8)
/* device name */
#define DEV_NAME_DSS_DPE "dss_dpe"
#define DEV_NAME_SPI "spi_dev0"
#define DEV_NAME_HDMI "hdmi"
#define DEV_NAME_DP "dp"
#define DEV_NAME_MIPI2RGB "mipi2rgb"
#define DEV_NAME_RGB2MIPI "rgb2mipi"
#define DEV_NAME_MIPIDSI "mipi_dsi"
#define DEV_NAME_FB "hisi_fb"
#define DEV_NAME_PWM "hisi_pwm"
#define DEV_NAME_BLPWM "hisi_blpwm"
#define DEV_NAME_LCD_BKL "lcd_backlight0"
/* vcc name */
#define REGULATOR_PDP_NAME "regulator_dsssubsys"
#define REGULATOR_MMBUF "regulator_mmbuf"
#define REGULATOR_MEDIA_NAME "regulator_media_subsys"
/* irq name */
#define IRQ_PDP_NAME "irq_pdp"
#define IRQ_SDP_NAME "irq_sdp"
#define IRQ_ADP_NAME "irq_adp"
#define IRQ_MDC_NAME "irq_mdc"
#define IRQ_DSI0_NAME "irq_dsi0"
#define IRQ_DSI1_NAME "irq_dsi1"
/* dts compatible */
#define DTS_COMP_FB_NAME "hisilicon,hisifb"
#define DTS_COMP_PWM_NAME "hisilicon,hisipwm"
#define DTS_COMP_BLPWM_NAME "hisilicon,hisiblpwm"
#define DTS_PATH_LOGO_BUFFER "/reserved-memory/logo-buffer"
/* lcd resource name */
#define LCD_BL_TYPE_NAME "lcd-bl-type"
#define FPGA_FLAG_NAME "fpga_flag"
#define LCD_DISPLAY_TYPE_NAME "lcd-display-type"
#define LCD_IFBC_TYPE_NAME "lcd-ifbc-type"
/* backlight type */
#define BL_SET_BY_NONE BIT(0)
#define BL_SET_BY_PWM BIT(1)
#define BL_SET_BY_BLPWM BIT(2)
#define BL_SET_BY_MIPI BIT(3)
#define BL_SET_BY_SH_BLPWM BIT(4)
/* supported display effect type */
#define COMFORM_MODE BIT(0)
#define ACM_COLOR_ENHANCE_MODE BIT(1)
#define IC_COLOR_ENHANCE_MODE BIT(2)
#define CINEMA_MODE BIT(3)
#define VR_MODE BIT(4)
#define FPS_30_60_SENCE_MODE BIT(5)
#define LED_RG_COLOR_TEMP_MODE BIT(16)
#define GAMMA_MAP BIT(19)
#define LCD_BL_IC_NAME_MAX (50)
#define DEV_DSS_VOLTAGE_ID (20)
enum MIPI_LP11_MODE {
MIPI_NORMAL_LP11 = 0,
MIPI_SHORT_LP11 = 1,
MIPI_DISABLE_LP11 = 2,
};
/* resource desc */
struct resource_desc {
uint32_t flag;
char *name;
uint32_t *value;
};
/* dtype for vcc */
enum {
DTYPE_VCC_GET,
DTYPE_VCC_PUT,
DTYPE_VCC_ENABLE,
DTYPE_VCC_DISABLE,
DTYPE_VCC_SET_VOLTAGE,
};
/* vcc desc */
struct vcc_desc {
int dtype;
char *id;
struct regulator **regulator;
int min_uV;
int max_uV;
int waittype;
int wait;
};
/* pinctrl operation */
enum {
DTYPE_PINCTRL_GET,
DTYPE_PINCTRL_STATE_GET,
DTYPE_PINCTRL_SET,
DTYPE_PINCTRL_PUT,
};
/* pinctrl state */
enum {
DTYPE_PINCTRL_STATE_DEFAULT,
DTYPE_PINCTRL_STATE_IDLE,
};
/* pinctrl data */
struct pinctrl_data {
struct pinctrl *p;
struct pinctrl_state *pinctrl_def;
struct pinctrl_state *pinctrl_idle;
};
struct pinctrl_cmd_desc {
int dtype;
struct pinctrl_data *pctrl_data;
int mode;
};
/* dtype for gpio */
enum {
DTYPE_GPIO_REQUEST,
DTYPE_GPIO_FREE,
DTYPE_GPIO_INPUT,
DTYPE_GPIO_OUTPUT,
};
/* gpio desc */
struct gpio_desc {
int dtype;
int waittype;
int wait;
char *label;
uint32_t *gpio;
int value;
};
enum bl_control_mode {
REG_ONLY_MODE = 1,
PWM_ONLY_MODE,
MUTI_THEN_RAMP_MODE,
RAMP_THEN_MUTI_MODE,
I2C_ONLY_MODE = 6,
BLPWM_AND_CABC_MODE,
COMMON_IC_MODE = 8,
};
/*******************************************************************************
** FUNCTIONS PROTOTYPES
*/
#define MIPI_DPHY_NUM (2)
extern uint32_t g_dts_resouce_ready;
int resource_cmds_tx(struct platform_device *pdev,
struct resource_desc *cmds, int cnt);
int vcc_cmds_tx(struct platform_device *pdev, struct vcc_desc *cmds, int cnt);
int pinctrl_cmds_tx(struct platform_device *pdev, struct pinctrl_cmd_desc *cmds, int cnt);
int gpio_cmds_tx(struct gpio_desc *cmds, int cnt);
extern struct spi_device *g_spi_dev;
int spi_cmds_tx(struct spi_device *spi, struct spi_cmd_desc *cmds, int cnt);
int hisi_pwm_set_backlight(struct backlight_device *bl, uint32_t bl_level);
int hisi_pwm_off(void);
int hisi_pwm_on(void);
int hisi_lcd_backlight_on(struct drm_panel *p);
int hisi_lcd_backlight_off(struct drm_panel *p);
#endif /* KIRIN_FB_PANEL_H */
+27 -9
View File
@@ -22,7 +22,11 @@
#include <linux/hisi/hisi_ion.h>
#include "kirin_drm_drv.h"
#if defined (CONFIG_HISI_FB_970)
#include "kirin970_dpe_reg.h"
#else
#include "kirin_dpe_reg.h"
#endif
#include "kirin_drm_dpe_utils.h"
#include "drm_crtc.h"
@@ -30,7 +34,7 @@
//#define CONFIG_HISI_FB_HEAP_CARVEOUT_USED
#define FBDEV_BUFFER_NUM 3
#define FBDEV_BUFFER_NUM 2
struct fb_dmabuf_export
{
__u32 fd;
@@ -110,6 +114,9 @@ unsigned long kirin_alloc_fb_buffer(struct kirin_fbdev *fbdev, int size)
fbdev->ion_client = client;
fbdev->ion_handle = handle;
DRM_INFO("fbdev->smem_start = 0x%x, fbdev->screen_base = 0x%x\n",
fbdev->smem_start, fbdev->screen_base);
return buf_addr;
err_ion_get_addr:
@@ -157,11 +164,13 @@ static int kirin_fbdev_mmap(struct fb_info *info, struct vm_area_struct * vma)
addr = vma->vm_start;
offset = vma->vm_pgoff * PAGE_SIZE;
size = vma->vm_end - vma->vm_start;
DRM_INFO("addr = 0x%x, offset = %d, size = %d!\n", addr, offset, size);
if (size > info->fix.smem_len) {
DRM_ERROR("size=%lu is out of range(%u)!\n", size, info->fix.smem_len);
return -EFAULT;
}
DRM_INFO("fbdev->smem_start = 0x%x, fbdev->screen_base = 0x%x\n",
fbdev->smem_start, fbdev->screen_base);
for_each_sg(table->sgl, sg, table->nents, i) {
page = sg_page(sg);
@@ -184,10 +193,15 @@ static int kirin_fbdev_mmap(struct fb_info *info, struct vm_area_struct * vma)
}
addr += len;
if (addr >= vma->vm_end)
if (addr >= vma->vm_end) {
DRM_ERROR("addr = 0x%x!, vma->vm_end = 0x%x\n", addr, vma->vm_end);
return 0;
}
}
DRM_INFO("kirin_fbdev_mmap addr = 0x%x!\n", addr);
return 0;
}
@@ -211,6 +225,7 @@ static int kirin_dmabuf_export(struct fb_info *info, void __user *argp)
if (dmabuf_export.fd < 0) {
DRM_ERROR("failed to ion_share!\n");
}
DRM_INFO("dmabuf_export.fd = %d.\n", dmabuf_export.fd);
ret = copy_to_user(argp, &dmabuf_export, sizeof(struct fb_dmabuf_export));
if (ret) {
@@ -228,12 +243,15 @@ static int kirin_dss_online_compose(struct fb_info *info, void __user *argp)
struct drm_fb_helper *helper;
struct kirin_drm_private *priv;
struct drm_plane *plane;
struct kirin_fbdev *fbdev;
struct drm_dss_layer layer;
helper = (struct drm_fb_helper *)info->par;
priv = helper->dev->dev_private;
plane =priv->crtc[0]->primary;
plane = priv->crtc[0]->primary;
fbdev = to_kirin_fbdev(helper);
ret = copy_from_user(&layer, argp, sizeof(struct drm_dss_layer));
if (ret) {
@@ -241,7 +259,7 @@ static int kirin_dss_online_compose(struct fb_info *info, void __user *argp)
return -EINVAL;
}
hisi_dss_online_play(plane, &layer);
hisi_dss_online_play(fbdev, plane, &layer);
return ret;
}
@@ -326,7 +344,7 @@ static int kirin_fbdev_create(struct drm_fb_helper *helper,
/* allocate backing bo */
size = mode_cmd.pitches[0] * mode_cmd.height;
DRM_DEBUG("allocating %d bytes for fb %d", size, dev->primary->index);
DRM_DEBUG("allocating %d bytes for fb %d \n", size, dev->primary->index);
fb = kirin_framebuffer_init(dev, &mode_cmd);
if (IS_ERR(fb)) {
@@ -356,7 +374,7 @@ static int kirin_fbdev_create(struct drm_fb_helper *helper,
goto fail_unlock;
}
DRM_DEBUG("fbi=%p, dev=%p", fbi, dev);
DRM_DEBUG("fbi=%p, dev=%p \n", fbi, dev);
fbdev->fb = fb;
helper->fb = fb;
@@ -376,8 +394,8 @@ static int kirin_fbdev_create(struct drm_fb_helper *helper,
fbi->fix.smem_start = fbdev->smem_start;
fbi->fix.smem_len = fbdev->screen_size;
DRM_DEBUG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres);
DRM_DEBUG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height);
DRM_DEBUG("par=%p, %dx%d \n", fbi->par, fbi->var.xres, fbi->var.yres);
DRM_DEBUG("allocated %dx%d fb \n", fbdev->fb->width, fbdev->fb->height);
mutex_unlock(&dev->struct_mutex);
@@ -0,0 +1,400 @@
/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* 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 <drm/drmP.h>
#include <linux/clk.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/of_address.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include "drm_mipi_dsi.h"
#include "kirin_drm_dpe_utils.h"
#include "kirin_fb_panel.h"
#include "dw_dsi_reg.h"
/* default pwm clk */
#define DEFAULT_PWM_CLK_RATE (80 * 1000000L)
static char __iomem *hisifd_pwm_base;
static char __iomem *hisi_peri_crg_base;
static struct clk *g_pwm_clk;
static struct platform_device *g_pwm_pdev;
static int g_pwm_on;
static struct pinctrl_data pwmpctrl;
static struct pinctrl_cmd_desc pwm_pinctrl_init_cmds[] = {
{DTYPE_PINCTRL_GET, &pwmpctrl, 0},
{DTYPE_PINCTRL_STATE_GET, &pwmpctrl, DTYPE_PINCTRL_STATE_DEFAULT},
{DTYPE_PINCTRL_STATE_GET, &pwmpctrl, DTYPE_PINCTRL_STATE_IDLE},
};
static struct pinctrl_cmd_desc pwm_pinctrl_normal_cmds[] = {
{DTYPE_PINCTRL_SET, &pwmpctrl, DTYPE_PINCTRL_STATE_DEFAULT},
};
static struct pinctrl_cmd_desc pwm_pinctrl_lowpower_cmds[] = {
{DTYPE_PINCTRL_SET, &pwmpctrl, DTYPE_PINCTRL_STATE_IDLE},
};
static struct pinctrl_cmd_desc pwm_pinctrl_finit_cmds[] = {
{DTYPE_PINCTRL_PUT, &pwmpctrl, 0},
};
#define PWM_LOCK_OFFSET (0x0000)
#define PWM_CTL_OFFSET (0X0004)
#define PWM_CFG_OFFSET (0x0008)
#define PWM_PR0_OFFSET (0x0100)
#define PWM_PR1_OFFSET (0x0104)
#define PWM_C0_MR_OFFSET (0x0300)
#define PWM_C0_MR0_OFFSET (0x0304)
#define PWM_OUT_PRECISION (800)
int pinctrl_cmds_tx(struct platform_device *pdev, struct pinctrl_cmd_desc *cmds, int cnt)
{
int ret = 0;
int i = 0;
struct pinctrl_cmd_desc *cm = NULL;
cm = cmds;
for (i = 0; i < cnt; i++) {
if (cm == NULL) {
DRM_ERROR("cm is null! index=%d\n", i);
continue;
}
if (cm->dtype == DTYPE_PINCTRL_GET) {
if (NULL == pdev) {
DRM_ERROR("pdev is NULL");
return -EINVAL;
}
cm->pctrl_data->p = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(cm->pctrl_data->p)) {
ret = -1;
DRM_ERROR("failed to get p, index=%d!\n", i);
goto err;
}
} else if (cm->dtype == DTYPE_PINCTRL_STATE_GET) {
if (cm->mode == DTYPE_PINCTRL_STATE_DEFAULT) {
cm->pctrl_data->pinctrl_def = pinctrl_lookup_state(cm->pctrl_data->p, PINCTRL_STATE_DEFAULT);
if (IS_ERR(cm->pctrl_data->pinctrl_def)) {
ret = -1;
DRM_ERROR("failed to get pinctrl_def, index=%d!\n", i);
goto err;
}
} else if (cm->mode == DTYPE_PINCTRL_STATE_IDLE) {
cm->pctrl_data->pinctrl_idle = pinctrl_lookup_state(cm->pctrl_data->p, PINCTRL_STATE_IDLE);
if (IS_ERR(cm->pctrl_data->pinctrl_idle)) {
ret = -1;
DRM_ERROR("failed to get pinctrl_idle, index=%d!\n", i);
goto err;
}
} else {
ret = -1;
DRM_ERROR("unknown pinctrl type to get!\n");
goto err;
}
} else if (cm->dtype == DTYPE_PINCTRL_SET) {
if (cm->mode == DTYPE_PINCTRL_STATE_DEFAULT) {
if (cm->pctrl_data->p && cm->pctrl_data->pinctrl_def) {
ret = pinctrl_select_state(cm->pctrl_data->p, cm->pctrl_data->pinctrl_def);
if (ret) {
DRM_ERROR("could not set this pin to default state!\n");
ret = -1;
goto err;
}
}
} else if (cm->mode == DTYPE_PINCTRL_STATE_IDLE) {
if (cm->pctrl_data->p && cm->pctrl_data->pinctrl_idle) {
ret = pinctrl_select_state(cm->pctrl_data->p, cm->pctrl_data->pinctrl_idle);
if (ret) {
DRM_ERROR("could not set this pin to idle state!\n");
ret = -1;
goto err;
}
}
} else {
ret = -1;
DRM_ERROR("unknown pinctrl type to set!\n");
goto err;
}
} else if (cm->dtype == DTYPE_PINCTRL_PUT) {
if (cm->pctrl_data->p)
pinctrl_put(cm->pctrl_data->p);
} else {
DRM_ERROR("not supported command type!\n");
ret = -1;
goto err;
}
cm++;
}
return 0;
err:
return ret;
}
int hisi_pwm_set_backlight(struct backlight_device *bl, uint32_t bl_level)
{
char __iomem *pwm_base = NULL;
uint32_t bl_max = bl->props.max_brightness;
pwm_base = hisifd_pwm_base;
if (!pwm_base) {
DRM_ERROR("pwm_base is null!\n");
return -EINVAL;
}
DRM_INFO("bl_level=%d.\n", bl_level);
if (bl_max < 1) {
DRM_ERROR("bl_max(%d) is out of range!!", bl_max);
return -EINVAL;
}
if (bl_level > bl_max) {
bl_level = bl_max;
}
bl_level = (bl_level * PWM_OUT_PRECISION) / bl_max;
outp32(pwm_base + PWM_LOCK_OFFSET, 0x1acce551);
outp32(pwm_base + PWM_CTL_OFFSET, 0x0);
outp32(pwm_base + PWM_CFG_OFFSET, 0x2);
outp32(pwm_base + PWM_PR0_OFFSET, 0x1);
outp32(pwm_base + PWM_PR1_OFFSET, 0x2);
outp32(pwm_base + PWM_CTL_OFFSET, 0x1);
outp32(pwm_base + PWM_C0_MR_OFFSET, (PWM_OUT_PRECISION - 1));
outp32(pwm_base + PWM_C0_MR0_OFFSET, bl_level);
return 0;
}
int hisi_pwm_on(void)
{
struct clk *clk_tmp = NULL;
char __iomem *pwm_base = NULL;
char __iomem *peri_crg_base = NULL;
int ret = 0;
DRM_INFO(" +.\n");
peri_crg_base = hisi_peri_crg_base;
if (!peri_crg_base) {
DRM_ERROR("peri_crg_base is NULL");
return -EINVAL;
}
pwm_base = hisifd_pwm_base;
if (!pwm_base) {
DRM_ERROR("pwm_base is null!\n");
return -EINVAL;
}
if (g_pwm_on == 1)
return 0;
// dis-reset pwm
outp32(peri_crg_base + PERRSTDIS2, 0x1);
clk_tmp = g_pwm_clk;
if (clk_tmp) {
ret = clk_prepare(clk_tmp);
if (ret) {
DRM_ERROR("dss_pwm_clk clk_prepare failed, error=%d!\n", ret);
return -EINVAL;
}
ret = clk_enable(clk_tmp);
if (ret) {
DRM_ERROR("dss_pwm_clk clk_enable failed, error=%d!\n", ret);
return -EINVAL;
}
DRM_INFO("dss_pwm_clk clk_enable successed, ret=%d!\n", ret);
}
ret = pinctrl_cmds_tx(g_pwm_pdev, pwm_pinctrl_normal_cmds,
ARRAY_SIZE(pwm_pinctrl_normal_cmds));
//if enable PWM, please set IOMG_004 in IOC_AO module
//set IOMG_004: select PWM_OUT0
g_pwm_on = 1;
return ret;
}
int hisi_pwm_off(void)
{
struct clk *clk_tmp = NULL;
char __iomem *pwm_base = NULL;
char __iomem *peri_crg_base = NULL;
int ret = 0;
peri_crg_base = hisi_peri_crg_base;
if (!peri_crg_base) {
DRM_ERROR("peri_crg_base is NULL");
return -EINVAL;
}
pwm_base = hisifd_pwm_base;
if (!pwm_base) {
DRM_ERROR("pwm_base is null!\n");
return -EINVAL;
}
if (g_pwm_on == 0)
return 0;
ret = pinctrl_cmds_tx(g_pwm_pdev, pwm_pinctrl_lowpower_cmds,
ARRAY_SIZE(pwm_pinctrl_lowpower_cmds));
clk_tmp = g_pwm_clk;
if (clk_tmp) {
clk_disable(clk_tmp);
clk_unprepare(clk_tmp);
}
//reset pwm
outp32(peri_crg_base + PERRSTEN2, 0x1);
g_pwm_on = 0;
return ret;
}
static int hisi_pwm_probe(struct platform_device *pdev)
{
struct device_node *np = NULL;
int ret = 0;
if (NULL == pdev) {
DRM_ERROR("pdev is NULL");
return -EINVAL;
}
g_pwm_pdev = pdev;
np = of_find_compatible_node(NULL, NULL, DTS_COMP_PWM_NAME);
if (!np) {
DRM_ERROR("NOT FOUND device node %s!\n", DTS_COMP_PWM_NAME);
ret = -ENXIO;
goto err_return;
}
/* get pwm reg base */
hisifd_pwm_base = of_iomap(np, 0);
if (!hisifd_pwm_base) {
DRM_ERROR("failed to get pwm_base resource.\n");
return -ENXIO;
}
/* get peri_crg_base */
hisi_peri_crg_base = of_iomap(np, 1);
if (!hisi_peri_crg_base) {
DRM_ERROR("failed to get peri_crg_base resource.\n");
return -ENXIO;
}
/* pwm pinctrl init */
ret = pinctrl_cmds_tx(pdev, pwm_pinctrl_init_cmds,
ARRAY_SIZE(pwm_pinctrl_init_cmds));
if (ret != 0) {
DRM_ERROR("Init pwm pinctrl failed! ret=%d.\n", ret);
goto err_return;
}
/* get pwm clk resource */
g_pwm_clk = of_clk_get(np, 0);
if (IS_ERR(g_pwm_clk)) {
DRM_ERROR("%s clock not found: %d!\n",
np->name, (int)PTR_ERR(g_pwm_clk));
ret = -ENXIO;
goto err_return;
}
DRM_INFO("dss_pwm_clk:[%lu]->[%lu].\n",
DEFAULT_PWM_CLK_RATE, clk_get_rate(g_pwm_clk));
return 0;
err_return:
return ret;
}
static int hisi_pwm_remove(struct platform_device *pdev)
{
struct clk *clk_tmp = NULL;
int ret = 0;
ret = pinctrl_cmds_tx(pdev, pwm_pinctrl_finit_cmds,
ARRAY_SIZE(pwm_pinctrl_finit_cmds));
clk_tmp = g_pwm_clk;
if (clk_tmp) {
clk_put(clk_tmp);
clk_tmp = NULL;
}
return ret;
}
static const struct of_device_id hisi_pwm_match_table[] = {
{
.compatible = "hisilicon,hisipwm",
.data = NULL,
},
{},
};
MODULE_DEVICE_TABLE(of, hisi_pwm_match_table);
static struct platform_driver this_driver = {
.probe = hisi_pwm_probe,
.remove = hisi_pwm_remove,
.suspend = NULL,
.resume = NULL,
.shutdown = NULL,
.driver = {
.name = DEV_NAME_PWM,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(hisi_pwm_match_table),
},
};
static int __init hisi_pwm_init(void)
{
int ret = 0;
ret = platform_driver_register(&this_driver);
if (ret) {
DRM_ERROR("platform_driver_register failed, error=%d!\n", ret);
return ret;
}
return ret;
}
module_init(hisi_pwm_init);
MODULE_AUTHOR("cailiwei <cailiwei@hisilicon.com>");
MODULE_AUTHOR("zhangxiubin <zhangxiubin1@huawei.com>");
MODULE_DESCRIPTION("hisilicon Kirin SoCs' pwm driver");
MODULE_LICENSE("GPL v2");
+8
View File
@@ -81,4 +81,12 @@ config DRM_PANEL_SHARP_LS043T1LE01
Say Y here if you want to enable support for Sharp LS043T1LE01 qHD
(540x960) DSI panel as found on the Qualcomm APQ8074 Dragonboard
config DRM_PANEL_HIKEY960_NTE300NTS
tristate "Hikey960 NTE300NTS video mode panel"
depends on OF
depends on DRM_MIPI_DSI
help
Say Y here if you want to enable LCD panel driver for Hikey960&Hikey970 boadr.
Current support panel: NTE300NTS(1920X1200)
endmenu
+1
View File
@@ -6,3 +6,4 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o
obj-$(CONFIG_DRM_PANEL_HIKEY960_NTE300NTS) += panel-hikey960-nte300nts.o
@@ -0,0 +1,506 @@
/*
* HiKey LCD panel driver
* TODO: Add backlight adjustment support.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#include <linux/of.h>
#include <linux/gpio/consumer.h>
#include <video/mipi_display.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_panel.h>
#include "../hisilicon/kirin960/kirin_fb_panel.h"
#define REGFLAG_DELAY 0XFFE
struct hikey_panel {
struct drm_panel base;
struct mipi_dsi_device *dsi;
bool prepared;
bool enabled;
uint32_t bl_set_type;
struct backlight_device *backlight;
struct gpio_desc *gpio_pwr_en;
struct gpio_desc *gpio_bl_en;
struct gpio_desc *gpio_pwm;
struct regulator *vdd;
};
struct dsi_panel_cmd {
u32 cmd; /* cmd: DCS command */
u32 len; /* command payload length */
u8 data[64]; /* buffer containing the command payload */
};
/* backlight set type */
#define BL_SET_BY_NONE BIT(0)
#define BL_SET_BY_PWM BIT(1)
#define BL_SET_BY_BLPWM BIT(2)
#define BL_SET_BY_MIPI BIT(3)
#define BL_SET_BY_SH_BLPWM BIT(4)
static struct dsi_panel_cmd nte300nts_init_cmds[] = {
{0x01, 0, {0x00} },
{REGFLAG_DELAY, 5, {} },
{0xB0, 1, {0x00} },
{REGFLAG_DELAY, 2, {} },
{0xD6, 1, {0x01} },
{REGFLAG_DELAY, 2, {} },
{0xB3, 5, {0x14, 0x08, 0x00, 0x22, 0x00} },
{REGFLAG_DELAY, 2, {} },
{0xB4, 1, {0x0C} },
{REGFLAG_DELAY, 2, {} },
{0xB6, 2, {0x3A, 0xC3} },
{REGFLAG_DELAY, 2, {} },
{0x2A, 4, {0x00, 0x00, 0X04, 0XAF} },
{REGFLAG_DELAY, 2, {} },
{0x2B, 4, {0x00, 0x00, 0X07, 0X7F} },
{REGFLAG_DELAY, 2, {} },
{0x51, 1, {0xA6} },
{REGFLAG_DELAY, 2, {} },
{0x53, 1, {0x2C} },
{REGFLAG_DELAY, 2, {} },
{0x3A, 1, {0x66} },
{REGFLAG_DELAY, 2, {} },
{0x29, 0, {0x00} },
{REGFLAG_DELAY, 20, {} },
{0x11, 0, {0x00} },
{REGFLAG_DELAY, 150, {} },
};
static struct dsi_panel_cmd nte300nts_off_cmds[] = {
{0x28, 0, {0x00} },
{REGFLAG_DELAY, 20, {} },
{0x10, 0, {0x00} },
{REGFLAG_DELAY, 80, {} },
};
static int hikey_panel_write_cmds(struct mipi_dsi_device *dsi,
struct dsi_panel_cmd *cmds,
u32 count)
{
struct dsi_panel_cmd *cmd;
int ret = 0;
u32 i;
for (i = 0; i < count; i++) {
cmd = &cmds[i];
switch (cmd->cmd) {
case REGFLAG_DELAY:
msleep(cmd->len);
break;
default:
ret = mipi_dsi_dcs_write(dsi, cmd->cmd, cmd->data,
cmd->len);
}
}
return ret;
}
static inline struct hikey_panel *to_hikey_panel(struct drm_panel *panel)
{
return container_of(panel, struct hikey_panel, base);
}
static inline struct hikey_panel *bl_to_hikey_panel(struct backlight_device *backlight)
{
return container_of(backlight, struct hikey_panel, backlight);
}
int hisi_lcd_backlight_on(struct drm_panel *p)
{
struct hikey_panel *panel = to_hikey_panel(p);
int ret = 0;
if (panel->bl_set_type & BL_SET_BY_PWM) {
ret = hisi_pwm_on();
} else if (panel->bl_set_type & BL_SET_BY_MIPI) {
;
} else {
DRM_ERROR("No such bl_set_type(%d)!\n", panel->bl_set_type);
}
return ret;
}
static int hikey_panel_unprepare(struct drm_panel *p)
{
struct hikey_panel *panel = to_hikey_panel(p);
if (!panel->prepared)
return 0;
gpiod_set_value(panel->gpio_bl_en, 0);
gpiod_set_value(panel->gpio_pwm, 0);
panel->prepared = false;
return 0;
}
static int hikey_panel_prepare(struct drm_panel *p)
{
struct hikey_panel *panel = to_hikey_panel(p);
int ret;
if (panel->prepared)
return 0;
/*
* A minimum delay of 250ms is required after power-up until commands
* can be sent
*/
msleep(250);
/* init the panel */
ret = hikey_panel_write_cmds(panel->dsi, nte300nts_init_cmds,
ARRAY_SIZE(nte300nts_init_cmds));
if (ret < 0)
return ret;
hisi_lcd_backlight_on(p);
panel->prepared = true;
return 0;
}
static int hikey_panel_disable(struct drm_panel *p)
{
struct hikey_panel *panel = to_hikey_panel(p);
int ret;
if (!panel->enabled)
return 0;
ret = hikey_panel_write_cmds(panel->dsi, nte300nts_off_cmds,
ARRAY_SIZE(nte300nts_off_cmds));
if (ret < 0)
return ret;
panel->enabled = false;
return 0;
}
static int hikey_panel_enable(struct drm_panel *p)
{
struct hikey_panel *panel = to_hikey_panel(p);
if (panel->enabled)
return 0;
msleep(200);
gpiod_set_value(panel->gpio_bl_en, 1);
if (panel->backlight) {
panel->backlight->props.power = FB_BLANK_UNBLANK;
backlight_update_status(panel->backlight);
}
panel->enabled = true;
return 0;
}
static const struct drm_display_mode default_mode = {
.clock = 144000,
.hdisplay = 1200,
.hsync_start = 1200 + 200,
.hsync_end = 1200 + 200 + 12,
.htotal = 1200 + 12 + 60 + 200,
.vdisplay = 1920,
.vsync_start = 1920 + 8,
.vsync_end = 1920 + 8 + 2,
.vtotal = 1920 + 2 + 8 + 8,
};
static int hikey_panel_get_modes(struct drm_panel *panel)
{
struct drm_display_mode *mode;
mode = drm_mode_duplicate(panel->drm, &default_mode);
if (!mode) {
DRM_ERROR("failed to add mode %ux%ux@%u\n",
default_mode.hdisplay, default_mode.vdisplay,
default_mode.vrefresh);
return -ENOMEM;
}
drm_mode_set_name(mode);
drm_mode_probed_add(panel->connector, mode);
panel->connector->display_info.width_mm = 94;
panel->connector->display_info.height_mm = 151;
return 1;
}
static int hisi_bl_get_brightness(struct backlight_device *bl)
{
struct mipi_dsi_device *dsi = bl_get_data(bl);
int ret;
u16 brightness = bl->props.brightness;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
if (ret < 0)
return ret;
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
return brightness & 0xff;
}
static int hisi_bl_update_status(struct backlight_device *bl)
{
struct mipi_dsi_device *dsi = bl_get_data(bl);
struct hikey_panel *panel = bl_to_hikey_panel(bl);
struct dsi_panel_cmd *cmd;
int bl_level;
int ret;
u8 data[] = {0};
struct dsi_panel_cmd bl_cmd[] = {
{0x51, sizeof(data), data},
};
bl_level = bl->props.brightness;
DRM_INFO("bl_level is %d\n", bl_level);
hisi_pwm_set_backlight(bl, bl_level);
return 0;
}
static const struct backlight_ops dsi_bl_ops = {
.update_status = hisi_bl_update_status,
.get_brightness = hisi_bl_get_brightness,
};
static struct backlight_device *
drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
struct backlight_properties props;
memset(&props, 0, sizeof(props));
props.type = BACKLIGHT_RAW;
props.brightness = 255;
props.max_brightness = 255;
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
&dsi_bl_ops, &props);
}
static const struct drm_panel_funcs hikey_panel_funcs = {
.get_modes = hikey_panel_get_modes,
.enable = hikey_panel_enable,
.disable = hikey_panel_disable,
.prepare = hikey_panel_prepare,
.unprepare = hikey_panel_unprepare,
};
static int hikey_panel_add(struct hikey_panel *panel)
{
struct device *dev = &panel->dsi->dev;
int ret;
drm_panel_init(&panel->base);
panel->base.funcs = &hikey_panel_funcs;
panel->base.dev = dev;
panel->bl_set_type = BL_SET_BY_PWM;
ret = drm_panel_add(&panel->base);
if (ret)
return ret;
return 0;
}
static void hikey_panel_del(struct hikey_panel *panel)
{
if (panel->base.dev)
drm_panel_remove(&panel->base);
}
static int hikey_panel_parse_dt(struct hikey_panel *panel)
{
struct device *dev = &panel->dsi->dev;
struct device_node *backlight;
int ret = 0;
panel->gpio_pwr_en =
devm_gpiod_get_optional(dev, "pwr-en", GPIOD_OUT_HIGH);
if (IS_ERR(panel->gpio_pwr_en))
return PTR_ERR(panel->gpio_pwr_en);
panel->gpio_bl_en =
devm_gpiod_get_optional(dev, "bl-en", GPIOD_OUT_LOW);
if (IS_ERR(panel->gpio_bl_en))
return PTR_ERR(panel->gpio_bl_en);
panel->gpio_pwm =
devm_gpiod_get_optional(dev, "pwm", GPIOD_OUT_LOW);
if (IS_ERR(panel->gpio_pwm))
return PTR_ERR(panel->gpio_pwm);
panel->vdd = devm_regulator_get(dev, "vdd");
if (IS_ERR(panel->vdd)) {
ret = PTR_ERR(panel->vdd);
return ret;
}
ret = regulator_set_voltage(panel->vdd, 1800000, 1800000);
if (ret)
return ret;
ret = regulator_enable(panel->vdd);
if (ret)
return ret;
panel->backlight = drm_panel_create_dsi_backlight(panel->dsi);
if (IS_ERR(panel->backlight)) {
ret = PTR_ERR(panel->backlight);
dev_err(dev, "failed to register backlight %d\n", ret);
return ret;
}
return 0;
}
static int hikey_panel_attach_dsi(struct mipi_dsi_device *dsi)
{
int ret;
//dsi->phy_clock = 864000; /* in kHz */
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_HSE |
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
ret = mipi_dsi_attach(dsi);
if (ret) {
DRM_ERROR("failed to attach dsi to host\n");
return ret;
}
return 0;
}
static int hikey_panel_probe(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
struct hikey_panel *panel;
int ret;
panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
if (!panel)
return -ENOMEM;
panel->dsi = dsi;
ret = hikey_panel_parse_dt(panel);
if (ret)
return ret;
ret = hikey_panel_add(panel);
if (ret)
return ret;
ret = hikey_panel_attach_dsi(dsi);
if (ret) {
hikey_panel_del(panel);
return ret;
}
mipi_dsi_set_drvdata(dsi, panel);
return 0;
}
static int hikey_panel_remove(struct mipi_dsi_device *dsi)
{
struct hikey_panel *panel = mipi_dsi_get_drvdata(dsi);
int ret;
ret = hikey_panel_disable(&panel->base);
if (ret < 0)
DRM_ERROR("failed to disable panel: %d\n", ret);
ret = mipi_dsi_detach(dsi);
if (ret < 0)
DRM_ERROR("failed to detach from DSI host: %d\n", ret);
drm_panel_detach(&panel->base);
hikey_panel_del(panel);
return 0;
}
static void hikey_panel_shutdown(struct mipi_dsi_device *dsi)
{
struct hikey_panel *panel = mipi_dsi_get_drvdata(dsi);
hikey_panel_disable(&panel->base);
}
static const struct of_device_id panel_of_match[] = {
{ .compatible = "hisilicon,mipi-hikey", },
{ }
};
MODULE_DEVICE_TABLE(of, panel_of_match);
static struct mipi_dsi_driver hikey_panel_driver = {
.driver = {
.name = "hikey-lcd-panel",
.of_match_table = panel_of_match,
},
.probe = hikey_panel_probe,
.remove = hikey_panel_remove,
.shutdown = hikey_panel_shutdown,
};
module_mipi_dsi_driver(hikey_panel_driver);
MODULE_DESCRIPTION("NTE300NTS (1920x1200) video mode panel driver");
MODULE_LICENSE("GPL v2");
+2058
View File
File diff suppressed because it is too large Load Diff