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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
+4267
File diff suppressed because it is too large
Load Diff
Regular → Executable
+139
-5
@@ -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;
|
||||
|
||||
Regular → Executable
+349
-19
@@ -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);
|
||||
|
||||
|
||||
Regular → Executable
+24
-3
@@ -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__ */
|
||||
|
||||
Regular → Executable
+306
-63
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Regular → Executable
+448
-39
@@ -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 */
|
||||
Regular → Executable
+27
-9
@@ -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");
|
||||
@@ -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
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user