From: Chen Feng <puck.chen@xxxxxxxxxxxxx> Add initial driver for hikey960 DRM driver, backported from OOT tree. Later patches will be needed to make this driver work. [jstultz: Rework patchset to use upstream adv7511 and remove duplicated code] [mchehab+huawei@xxxxxxxxxx: port just a subset of the original patch and place it at staging] Signed-off-by: Chen Feng <puck.chen@xxxxxxxxxxxxx> Signed-off-by: Liwei Cai <cailiwei@xxxxxxxxxxxxx> Signed-off-by: John Stultz <john.stultz@xxxxxxxxxx> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@xxxxxxxxxx> --- drivers/staging/hikey9xx/gpu/Kconfig | 52 + drivers/staging/hikey9xx/gpu/Makefile | 12 + drivers/staging/hikey9xx/gpu/dw_drm_dsi.c | 1650 +++++++++ drivers/staging/hikey9xx/gpu/dw_dsi_reg.h | 145 + drivers/staging/hikey9xx/gpu/kirin_dpe_reg.h | 3114 +++++++++++++++++ .../hikey9xx/gpu/kirin_drm_dpe_utils.c | 731 ++++ .../hikey9xx/gpu/kirin_drm_dpe_utils.h | 58 + drivers/staging/hikey9xx/gpu/kirin_drm_drv.c | 380 ++ drivers/staging/hikey9xx/gpu/kirin_drm_drv.h | 60 + drivers/staging/hikey9xx/gpu/kirin_drm_dss.c | 701 ++++ .../hikey9xx/gpu/kirin_drm_overlay_utils.c | 1288 +++++++ drivers/staging/hikey9xx/gpu/kirin_fb.c | 94 + drivers/staging/hikey9xx/gpu/kirin_fbdev.c | 470 +++ 13 files changed, 8755 insertions(+) create mode 100644 drivers/staging/hikey9xx/gpu/Kconfig create mode 100644 drivers/staging/hikey9xx/gpu/Makefile create mode 100644 drivers/staging/hikey9xx/gpu/dw_drm_dsi.c create mode 100644 drivers/staging/hikey9xx/gpu/dw_dsi_reg.h create mode 100644 drivers/staging/hikey9xx/gpu/kirin_dpe_reg.h create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.c create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.h create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_drv.c create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_drv.h create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_dss.c create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c create mode 100644 drivers/staging/hikey9xx/gpu/kirin_fb.c create mode 100644 drivers/staging/hikey9xx/gpu/kirin_fbdev.c diff --git a/drivers/staging/hikey9xx/gpu/Kconfig b/drivers/staging/hikey9xx/gpu/Kconfig new file mode 100644 index 000000000000..5533ee624f29 --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/Kconfig @@ -0,0 +1,52 @@ +config DRM_HISI_KIRIN + tristate "DRM Support for Hisilicon Kirin series SoCs Platform" + depends on DRM && OF && ARM64 + select DRM_KMS_HELPER + select DRM_GEM_CMA_HELPER + select DRM_KMS_CMA_HELPER + select HISI_KIRIN_DW_DSI + help + Choose this option if you have a hisilicon Kirin chipsets(hi6220). + If M is selected the module will be called kirin-drm. + +config DRM_KIRIN_960 + tristate "DRM Support for Hisilicon Kirin960 series SoCs Platform" + depends on DRM && OF && ARM64 + select DRM_KMS_HELPER + select DRM_GEM_CMA_HELPER + select DRM_KMS_CMA_HELPER + select HISI_KIRIN_DW_DSI + help + Choose this option if you have a hisilicon Kirin chipsets(kirin960). + If M is selected the module will be called kirin-drm. + +config HISI_KIRIN_DW_DSI + tristate "HiSilicon Kirin specific extensions for Synopsys DW MIPI DSI" + depends on DRM_HISI_KIRIN || DRM_KIRIN_960 + select DRM_MIPI_DSI + select DRM_PANEL + help + This selects support for HiSilicon Kirin SoC specific extensions for + the Synopsys DesignWare DSI driver. If you want to enable MIPI DSI on + hi6220 based SoC, you should selet this option. + +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 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. diff --git a/drivers/staging/hikey9xx/gpu/Makefile b/drivers/staging/hikey9xx/gpu/Makefile new file mode 100644 index 000000000000..42d1ed179264 --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/Makefile @@ -0,0 +1,12 @@ +EXTRA_CFLAGS += \ + -Iinclude/drm + +kirin-drm-y := kirin_fbdev.o \ + kirin_fb.o \ + kirin_drm_drv.o \ + kirin_drm_dss.o \ + kirin_drm_dpe_utils.o \ + kirin_drm_overlay_utils.o \ + +obj-$(CONFIG_DRM_KIRIN_960) += kirin-drm.o +obj-$(CONFIG_HISI_KIRIN_DW_DSI) += dw_drm_dsi.o diff --git a/drivers/staging/hikey9xx/gpu/dw_drm_dsi.c b/drivers/staging/hikey9xx/gpu/dw_drm_dsi.c new file mode 100644 index 000000000000..1d1d4f49609c --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/dw_drm_dsi.c @@ -0,0 +1,1650 @@ +/* + * DesignWare MIPI DSI Host Controller v1.02 driver + * + * Copyright (c) 2016 Linaro Limited. + * Copyright (c) 2014-2016 Hisilicon Limited. + * + * Author: + * <shizongxuan@xxxxxxxxxx> + * <zhangxiubin@xxxxxxxxxx> + * + * 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. + * + */ + +#include <linux/clk.h> +#include <linux/component.h> +#include <linux/of_graph.h> +#include <linux/iopoll.h> +#include <video/mipi_display.h> +#include <linux/gpio/consumer.h> +#include <linux/of_address.h> + +#include <drm/drm_of.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_encoder_slave.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_panel.h> + +#include "dw_dsi_reg.h" +#include "kirin_dpe_reg.h" +#include "kirin_drm_dpe_utils.h" + +#define DTS_COMP_DSI_NAME "hisilicon,hi3660-dsi" + +#define MAX_TX_ESC_CLK 10 +#define ROUND(x, y) ((x) / (y) + \ + ((x) % (y) * 10 / (y) >= 5 ? 1 : 0)) +#define ROUND1(x, y) ((x) / (y) + ((x) % (y) ? 1 : 0)) +#define PHY_REF_CLK_RATE 19200000 +#define PHY_REF_CLK_PERIOD_PS (1000000000 / (PHY_REF_CLK_RATE / 1000)) + +#define encoder_to_dsi(encoder) \ + container_of(encoder, struct dw_dsi, encoder) +#define host_to_dsi(host) \ + container_of(host, struct dw_dsi, host) +#define connector_to_dsi(connector) \ + container_of(connector, struct dw_dsi, connector) +#define DSS_REDUCE(x) ((x) > 0 ? ((x) - 1) : (x)) + +enum dsi_output_client { + OUT_HDMI = 0, + OUT_PANEL, + OUT_MAX +}; + +struct mipi_phy_params { + u64 lane_byte_clk; + u32 clk_division; + + u32 clk_lane_lp2hs_time; + u32 clk_lane_hs2lp_time; + u32 data_lane_lp2hs_time; + u32 data_lane_hs2lp_time; + u32 clk2data_delay; + u32 data2clk_delay; + + u32 clk_pre_delay; + u32 clk_post_delay; + u32 clk_t_lpx; + u32 clk_t_hs_prepare; + u32 clk_t_hs_zero; + u32 clk_t_hs_trial; + u32 clk_t_wakeup; + u32 data_pre_delay; + u32 data_post_delay; + u32 data_t_lpx; + u32 data_t_hs_prepare; + u32 data_t_hs_zero; + u32 data_t_hs_trial; + u32 data_t_ta_go; + u32 data_t_ta_get; + u32 data_t_wakeup; + + u32 phy_stop_wait_time; + + u32 rg_vrefsel_vcm; + u32 rg_hstx_ckg_sel; + u32 rg_pll_fbd_div5f; + u32 rg_pll_fbd_div1f; + u32 rg_pll_fbd_2p; + u32 rg_pll_enbwt; + u32 rg_pll_fbd_p; + u32 rg_pll_fbd_s; + u32 rg_pll_pre_div1p; + u32 rg_pll_pre_p; + u32 rg_pll_vco_750m; + u32 rg_pll_lpf_rs; + u32 rg_pll_lpf_cs; + u32 rg_pll_enswc; + u32 rg_pll_chp; + + u32 pll_register_override; /*0x1E[0]*/ + u32 pll_power_down; /*0x1E[1]*/ + u32 rg_band_sel; /*0x1E[2]*/ + u32 rg_phase_gen_en; /*0x1E[3]*/ + u32 reload_sel; /*0x1E[4]*/ + u32 rg_pll_cp_p; /*0x1E[7:5]*/ + u32 rg_pll_refsel; /*0x16[1:0]*/ + u32 rg_pll_cp; /*0x16[7:5]*/ + u32 load_command; +}; + +struct dsi_hw_ctx { + void __iomem *base; + char __iomem *peri_crg_base; + + struct clk *dss_dphy0_ref_clk; + struct clk *dss_dphy1_ref_clk; + struct clk *dss_dphy0_cfg_clk; + struct clk *dss_dphy1_cfg_clk; + struct clk *dss_pclk_dsi0_clk; + struct clk *dss_pclk_dsi1_clk; +}; + +struct dw_dsi_client { + u32 lanes; + u32 phy_clock; /* in kHz */ + enum mipi_dsi_pixel_format format; + unsigned long mode_flags; +}; + +struct mipi_panel_info { + u8 dsi_version; + u8 vc; + u8 lane_nums; + u8 lane_nums_select_support; + u8 color_mode; + u32 dsi_bit_clk; /* clock lane(p/n) */ + u32 burst_mode; + u32 max_tx_esc_clk; + u8 non_continue_en; + + u32 dsi_bit_clk_val1; + u32 dsi_bit_clk_val2; + u32 dsi_bit_clk_val3; + u32 dsi_bit_clk_val4; + u32 dsi_bit_clk_val5; + u32 dsi_bit_clk_upt; + /*uint32_t dsi_pclk_rate;*/ + + u32 hs_wr_to_time; + + /* dphy config parameter adjust*/ + u32 clk_post_adjust; + u32 clk_pre_adjust; + u32 clk_pre_delay_adjust; + u32 clk_t_hs_exit_adjust; + u32 clk_t_hs_trial_adjust; + u32 clk_t_hs_prepare_adjust; + int clk_t_lpx_adjust; + u32 clk_t_hs_zero_adjust; + u32 data_post_delay_adjust; + int data_t_lpx_adjust; + u32 data_t_hs_prepare_adjust; + u32 data_t_hs_zero_adjust; + u32 data_t_hs_trial_adjust; + u32 rg_vrefsel_vcm_adjust; + + /*only for Chicago<3660> use*/ + u32 rg_vrefsel_vcm_clk_adjust; + u32 rg_vrefsel_vcm_data_adjust; +}; + +struct ldi_panel_info { + u32 h_back_porch; + u32 h_front_porch; + u32 h_pulse_width; + + /* + ** note: vbp > 8 if used overlay compose, + ** also lcd vbp > 8 in lcd power on sequence + */ + u32 v_back_porch; + u32 v_front_porch; + u32 v_pulse_width; + + u8 hsync_plr; + u8 vsync_plr; + u8 pixelclk_plr; + u8 data_en_plr; + + /* for cabc */ + u8 dpi0_overlap_size; + u8 dpi1_overlap_size; +}; + +struct dw_dsi { + struct drm_encoder encoder; + struct drm_bridge *bridge; + struct drm_panel *panel; + struct mipi_dsi_host host; + struct drm_connector connector; /* connector for panel */ + struct drm_display_mode cur_mode; + struct dsi_hw_ctx *ctx; + struct mipi_phy_params phy; + struct mipi_panel_info mipi; + struct ldi_panel_info ldi; + u32 lanes; + enum mipi_dsi_pixel_format format; + unsigned long mode_flags; + struct gpio_desc *gpio_mux; + struct dw_dsi_client client[OUT_MAX]; + enum dsi_output_client cur_client; + bool enable; +}; + +struct dsi_data { + struct dw_dsi dsi; + struct dsi_hw_ctx ctx; +}; + +struct dsi_phy_range { + u32 min_range_kHz; + u32 max_range_kHz; + u32 pll_vco_750M; + u32 hstx_ckg_sel; +}; + +static const struct dsi_phy_range dphy_range_info[] = { + { 46875, 62500, 1, 7 }, + { 62500, 93750, 0, 7 }, + { 93750, 125000, 1, 6 }, + { 125000, 187500, 0, 6 }, + { 187500, 250000, 1, 5 }, + { 250000, 375000, 0, 5 }, + { 375000, 500000, 1, 4 }, + { 500000, 750000, 0, 4 }, + { 750000, 1000000, 1, 0 }, + { 1000000, 1500000, 0, 0 } +}; + +void dsi_set_output_client(struct drm_device *dev) +{ + enum dsi_output_client client; + struct drm_connector *connector; + struct drm_encoder *encoder; + struct dw_dsi *dsi; + + mutex_lock(&dev->mode_config.mutex); + + /* find dsi encoder */ + drm_for_each_encoder(encoder, dev) + if (encoder->encoder_type == DRM_MODE_ENCODER_DSI) + break; + dsi = encoder_to_dsi(encoder); + + /* find HDMI connector */ + drm_for_each_connector(connector, dev) + if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) + break; + + /* + * set the proper dsi output client + */ + client = connector->status == connector_status_connected ? + OUT_HDMI : OUT_PANEL; + if (client != dsi->cur_client) { + /* associate bridge and dsi encoder */ + if (client == OUT_HDMI) + encoder->bridge = dsi->bridge; + else + encoder->bridge = NULL; + + gpiod_set_value_cansleep(dsi->gpio_mux, client); + dsi->cur_client = client; + /* let the userspace know panel connector status has changed */ + drm_sysfs_hotplug_event(dev); + DRM_INFO("client change to %s\n", client == OUT_HDMI ? + "HDMI" : "panel"); + } + + mutex_unlock(&dev->mode_config.mutex); +} +EXPORT_SYMBOL(dsi_set_output_client); + +static void get_dsi_phy_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; + u32 m_n_fract = 0; + u32 m_n_int = 0; + u64 lane_clock = 0; + u64 vco_div = 1; + + 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; + u32 clk_pre_delay_reality = 0; + u32 clk_t_hs_zero_reality = 0; + u32 clk_post_delay_reality = 0; + u32 data_t_hs_zero_reality = 0; + u32 data_post_delay_reality = 0; + u32 data_pre_delay_reality = 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; /*0x1E[2]*/ + 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; + } + } + + /*if set rg_pll_enswc=1, rg_pll_fbd_s can't be 0*/ + if (m_pll <= 8) { + phy_ctrl->rg_pll_fbd_s = 1; + phy_ctrl->rg_pll_enswc = 0; + + if (m_pll % 2 == 0) { + phy_ctrl->rg_pll_fbd_p = m_pll / 2; + } else { + if (n_pll == 1) { + n_pll *= 2; + phy_ctrl->rg_pll_fbd_p = (m_pll * 2) / 2; + } else { + DRM_ERROR("phy m_pll not support!m_pll = %d\n", m_pll); + return; + } + } + } else if (m_pll <= 300) { + if (m_pll % 2 == 0) + phy_ctrl->rg_pll_enswc = 0; + else + phy_ctrl->rg_pll_enswc = 1; + + phy_ctrl->rg_pll_fbd_s = 1; + phy_ctrl->rg_pll_fbd_p = m_pll / 2; + } else if (m_pll <= 315) { + phy_ctrl->rg_pll_fbd_p = 150; + phy_ctrl->rg_pll_fbd_s = m_pll - 2 * phy_ctrl->rg_pll_fbd_p; + phy_ctrl->rg_pll_enswc = 1; + } else { + DRM_ERROR("phy m_pll not support!m_pll = %d\n", m_pll); + return; + } + + phy_ctrl->rg_pll_pre_p = n_pll; + + lane_clock = m_pll * (DEFAULT_MIPI_CLK_RATE / n_pll) / vco_div; + DRM_INFO("Config : lane_clock = %llu\n", lane_clock); + + /*FIXME :*/ + phy_ctrl->rg_pll_cp = 1; /*0x16[7:5]*/ + phy_ctrl->rg_pll_cp_p = 3; /*0x1E[7:5]*/ + + /*test_code_0x14 other parameters config*/ + phy_ctrl->rg_pll_enbwt = 0; /*0x14[2]*/ + phy_ctrl->rg_pll_chp = 0; /*0x14[1:0]*/ + + /*test_code_0x16 other parameters config, 0x16[3:2] reserved*/ + phy_ctrl->rg_pll_lpf_cs = 0; /*0x16[4]*/ + phy_ctrl->rg_pll_refsel = 1; /*0x16[1:0]*/ + + /*test_code_0x1E other parameters config*/ + phy_ctrl->reload_sel = 1; /*0x1E[4]*/ + phy_ctrl->rg_phase_gen_en = 1; /*0x1E[3]*/ + phy_ctrl->pll_power_down = 0; /*0x1E[1]*/ + phy_ctrl->pll_register_override = 1; /*0x1E[0]*/ + + /*HSTX select VCM VREF*/ + phy_ctrl->rg_vrefsel_vcm = 0x55; + if (mipi->rg_vrefsel_vcm_clk_adjust != 0) + phy_ctrl->rg_vrefsel_vcm = (phy_ctrl->rg_vrefsel_vcm & 0x0F) | + ((mipi->rg_vrefsel_vcm_clk_adjust & 0x0F) << 4); + + if (mipi->rg_vrefsel_vcm_data_adjust != 0) + phy_ctrl->rg_vrefsel_vcm = (phy_ctrl->rg_vrefsel_vcm & 0xF0) | + (mipi->rg_vrefsel_vcm_data_adjust & 0x0F); + + /*if reload_sel = 1, need to set load_command*/ + phy_ctrl->load_command = 0x5A; + + /******************** clock/data lane parameters config ******************/ + accuracy = 10; + ui = 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 + mipi->clk_post_adjust * ui; + + /* D-PHY Specification : clk_pre >= 8*UI*/ + clk_pre = 8 * ui + mipi->clk_pre_adjust * ui; + + /* D-PHY Specification : clk_t_hs_exit >= 100ns*/ + clk_t_hs_exit = 1000 * 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*/ + if (mipi->clk_t_hs_prepare_adjust == 0) + mipi->clk_t_hs_prepare_adjust = 43; + + clk_t_hs_prepare = ((380 * accuracy + mipi->clk_t_hs_prepare_adjust * ui) <= (950 * accuracy - 8 * ui)) ? + (380 * accuracy + mipi->clk_t_hs_prepare_adjust * ui) : (950 * accuracy - 8 * ui); + + /* 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)) + 8 * ui + + 3 * 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*/ + if (mipi->data_t_hs_prepare_adjust == 0) + mipi->data_t_hs_prepare_adjust = 35; + + data_t_hs_prepare = ((400 * accuracy + 4 * ui + mipi->data_t_hs_prepare_adjust * ui) <= (850 * accuracy + 6 * ui - 8 * ui)) ? + (400 * accuracy + 4 * ui + mipi->data_t_hs_prepare_adjust * ui) : (850 * accuracy + 6 * ui - 8 * 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 = (((2000 * accuracy - clk_t_hs_prepare) >= 500 * accuracy) ? + ((2000 * accuracy - clk_t_hs_prepare)) : (500 * accuracy)) + + mipi->clk_t_lpx_adjust * ui; + + /* D-PHY Specification : clk_t_hs_zero + clk_t_hs_prepare >= 300 ns*/ + /* clocked by TXBYTECLKHS*/ + clk_t_hs_zero = 3000 * accuracy - clk_t_hs_prepare + 3 * unit_tx_byte_clk_hs + mipi->clk_t_hs_zero_adjust * ui; + + /* 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 = clk_t_lpx + mipi->data_t_lpx_adjust * ui; /*2000 * accuracy - 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 = 1450 * accuracy + 10 * ui - data_t_hs_prepare + + 3 * unit_tx_byte_clk_hs + mipi->data_t_hs_zero_adjust * ui; + + 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->data_t_ta_go = 4; + phy_ctrl->data_t_ta_get = 5; + + clk_pre_delay_reality = phy_ctrl->clk_pre_delay + 2; + clk_t_hs_zero_reality = phy_ctrl->clk_t_hs_zero + 8; + data_t_hs_zero_reality = phy_ctrl->data_t_hs_zero + 4; + data_post_delay_reality = phy_ctrl->data_post_delay + 4; + + phy_ctrl->clk_post_delay = phy_ctrl->data_t_hs_trial + ROUND1(clk_post, unit_tx_byte_clk_hs); + phy_ctrl->data_pre_delay = clk_pre_delay_reality + phy_ctrl->clk_t_lpx + + phy_ctrl->clk_t_hs_prepare + clk_t_hs_zero_reality + ROUND1(clk_pre, unit_tx_byte_clk_hs) ; + + clk_post_delay_reality = phy_ctrl->clk_post_delay + 4; + data_pre_delay_reality = phy_ctrl->data_pre_delay + 2; + + phy_ctrl->clk_lane_lp2hs_time = clk_pre_delay_reality + phy_ctrl->clk_t_lpx + + phy_ctrl->clk_t_hs_prepare + clk_t_hs_zero_reality + 3; + phy_ctrl->clk_lane_hs2lp_time = clk_post_delay_reality + phy_ctrl->clk_t_hs_trial + 3; + phy_ctrl->data_lane_lp2hs_time = data_pre_delay_reality + phy_ctrl->data_t_lpx + + phy_ctrl->data_t_hs_prepare + data_t_hs_zero_reality + 3; + phy_ctrl->data_lane_hs2lp_time = data_post_delay_reality + phy_ctrl->data_t_hs_trial + 3; + phy_ctrl->phy_stop_wait_time = clk_post_delay_reality + + phy_ctrl->clk_t_hs_trial + ROUND1(clk_t_hs_exit, unit_tx_byte_clk_hs) - + (data_post_delay_reality + 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) ? + (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" + "rg_vrefsel_vcm=%u\n" + "clk_pre_delay=%u\n" + "clk_post_delay=%u\n" + "clk_t_hs_prepare=%u\n" + "clk_t_lpx=%u\n" + "clk_t_hs_zero=%u\n" + "clk_t_hs_trial=%u\n" + "data_pre_delay=%u\n" + "data_post_delay=%u\n" + "data_t_hs_prepare=%u\n" + "data_t_lpx=%u\n" + "data_t_hs_zero=%u\n" + "data_t_hs_trial=%u\n" + "data_t_ta_go=%u\n" + "data_t_ta_get=%u\n", + 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->data_t_ta_go, + phy_ctrl->data_t_ta_get); + DRM_INFO("clk_lane_lp2hs_time=%u\n" + "clk_lane_hs2lp_time=%u\n" + "data_lane_lp2hs_time=%u\n" + "data_lane_hs2lp_time=%u\n" + "phy_stop_wait_time=%u\n", + 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 dw_dsi_set_mode(struct dw_dsi *dsi, enum dsi_work_mode mode) +{ + struct dsi_hw_ctx *ctx = dsi->ctx; + void __iomem *base = ctx->base; + + writel(RESET, base + PWR_UP); + writel(mode, base + MODE_CFG); + writel(POWERUP, base + PWR_UP); +} + +static void dsi_set_burst_mode(void __iomem *base, unsigned long flags) +{ + u32 val; + u32 mode_mask = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_VIDEO_SYNC_PULSE; + u32 non_burst_sync_pulse = MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_VIDEO_SYNC_PULSE; + u32 non_burst_sync_event = MIPI_DSI_MODE_VIDEO; + + /* + * choose video mode type + */ + if ((flags & mode_mask) == non_burst_sync_pulse) + val = DSI_NON_BURST_SYNC_PULSES; + else if ((flags & mode_mask) == non_burst_sync_event) + val = DSI_NON_BURST_SYNC_EVENTS; + else + val = DSI_BURST_SYNC_PULSES_1; + + set_reg(base + MIPIDSI_VID_MODE_CFG_OFFSET, val, 2, 0); +} + +/* + * dsi phy reg write function + */ +static void dsi_phy_tst_set(void __iomem *base, u32 reg, u32 val) +{ + u32 reg_write = 0x10000 + reg; + + /* + * latch reg first + */ + writel(reg_write, base + MIPIDSI_PHY_TST_CTRL1_OFFSET); + writel(0x02, base + MIPIDSI_PHY_TST_CTRL0_OFFSET); + writel(0x00, base + MIPIDSI_PHY_TST_CTRL0_OFFSET); + + /* + * then latch value + */ + writel(val, base + MIPIDSI_PHY_TST_CTRL1_OFFSET); + writel(0x02, base + MIPIDSI_PHY_TST_CTRL0_OFFSET); + writel(0x00, base + MIPIDSI_PHY_TST_CTRL0_OFFSET); +} + +static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base) +{ + u32 hline_time = 0; + u32 hsa_time = 0; + u32 hbp_time = 0; + u64 pixel_clk = 0; + u32 i = 0; + u32 id = 0; + unsigned long dw_jiffies = 0; + u32 tmp = 0; + bool is_ready = false; + struct mipi_panel_info *mipi = NULL; + dss_rect_t rect; + u32 cmp_stopstate_val = 0; + u32 lanes; + + WARN_ON(!dsi); + WARN_ON(!mipi_dsi_base); + + id = dsi->cur_client; + mipi = &dsi->mipi; + + if (mipi->max_tx_esc_clk == 0) { + DRM_INFO("max_tx_esc_clk is invalid!"); + mipi->max_tx_esc_clk = DEFAULT_MAX_TX_ESC_CLK; + } + + memset(&dsi->phy, 0, sizeof(struct mipi_phy_params)); + get_dsi_phy_ctrl(dsi, &dsi->phy); + + rect.x = 0; + rect.y = 0; + rect.w = dsi->cur_mode.hdisplay; + rect.h = dsi->cur_mode.vdisplay; + lanes = dsi->client[id].lanes - 1; + /***************Configure the DPHY start**************/ + + set_reg(mipi_dsi_base + MIPIDSI_PHY_IF_CFG_OFFSET, lanes, 2, 0); + set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, dsi->phy.clk_division, 8, 0); + set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, dsi->phy.clk_division, 8, 8); + + outp32(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x00000000); + + outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); + outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000001); + outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); + + /* 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) + + (dsi->phy.rg_pll_enbwt << 2) + dsi->phy.rg_pll_chp); + + /* physical configuration PLL II, M*/ + dsi_phy_tst_set(mipi_dsi_base, 0x15, dsi->phy.rg_pll_fbd_p); + + /* physical configuration PLL III*/ + dsi_phy_tst_set(mipi_dsi_base, 0x16, + (dsi->phy.rg_pll_cp << 5) + (dsi->phy.rg_pll_lpf_cs << 4) + + dsi->phy.rg_pll_refsel); + + /* physical configuration PLL IV, N*/ + dsi_phy_tst_set(mipi_dsi_base, 0x17, dsi->phy.rg_pll_pre_p); + + /* sets the analog characteristic of V reference in D-PHY TX*/ + dsi_phy_tst_set(mipi_dsi_base, 0x1D, dsi->phy.rg_vrefsel_vcm); + + /* MISC AFE Configuration*/ + dsi_phy_tst_set(mipi_dsi_base, 0x1E, + (dsi->phy.rg_pll_cp_p << 5) + (dsi->phy.reload_sel << 4) + + (dsi->phy.rg_phase_gen_en << 3) + (dsi->phy.rg_band_sel << 2) + + (dsi->phy.pll_power_down << 1) + dsi->phy.pll_register_override); + + /*reload_command*/ + dsi_phy_tst_set(mipi_dsi_base, 0x1F, dsi->phy.load_command); + + /* pre_delay of clock lane request setting*/ + dsi_phy_tst_set(mipi_dsi_base, 0x20, DSS_REDUCE(dsi->phy.clk_pre_delay)); + + /* post_delay of clock lane request setting*/ + dsi_phy_tst_set(mipi_dsi_base, 0x21, DSS_REDUCE(dsi->phy.clk_post_delay)); + + /* clock lane timing ctrl - t_lpx*/ + dsi_phy_tst_set(mipi_dsi_base, 0x22, DSS_REDUCE(dsi->phy.clk_t_lpx)); + + /* clock lane timing ctrl - t_hs_prepare*/ + dsi_phy_tst_set(mipi_dsi_base, 0x23, DSS_REDUCE(dsi->phy.clk_t_hs_prepare)); + + /* clock lane timing ctrl - t_hs_zero*/ + dsi_phy_tst_set(mipi_dsi_base, 0x24, DSS_REDUCE(dsi->phy.clk_t_hs_zero)); + + /* clock lane timing ctrl - t_hs_trial*/ + dsi_phy_tst_set(mipi_dsi_base, 0x25, dsi->phy.clk_t_hs_trial); + + for (i = 0; i <= lanes; i++) { + /* data lane pre_delay*/ + tmp = 0x30 + (i << 4); + dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_pre_delay)); + + /*data lane post_delay*/ + tmp = 0x31 + (i << 4); + dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_post_delay)); + + /* data lane timing ctrl - t_lpx*/ + dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_lpx)); + + /* data lane timing ctrl - t_hs_prepare*/ + tmp = 0x33 + (i << 4); + dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_hs_prepare)); + + /* data lane timing ctrl - t_hs_zero*/ + tmp = 0x34 + (i << 4); + dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_hs_zero)); + + /* data lane timing ctrl - t_hs_trial*/ + tmp = 0x35 + (i << 4); + dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_hs_trial)); + + /* data lane timing ctrl - t_ta_go*/ + tmp = 0x36 + (i << 4); + dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_ta_go)); + + /* data lane timing ctrl - t_ta_get*/ + tmp = 0x37 + (i << 4); + dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_ta_get)); + } + + outp32(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x00000007); + + is_ready = false; + dw_jiffies = jiffies + HZ / 2; + do { + tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET); + if ((tmp & 0x00000001) == 0x00000001) { + is_ready = true; + break; + } + } while (time_after(dw_jiffies, jiffies)); + + if (!is_ready) { + DRM_INFO("phylock is not ready!MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n", + tmp); + } + + if (lanes >= DSI_4_LANES) + cmp_stopstate_val = (BIT(4) | BIT(7) | BIT(9) | BIT(11)); + else if (lanes >= DSI_3_LANES) + cmp_stopstate_val = (BIT(4) | BIT(7) | BIT(9)); + else if (lanes >= DSI_2_LANES) + cmp_stopstate_val = (BIT(4) | BIT(7)); + else + cmp_stopstate_val = (BIT(4)); + + is_ready = false; + dw_jiffies = jiffies + HZ / 2; + do { + tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET); + if ((tmp & cmp_stopstate_val) == cmp_stopstate_val) { + is_ready = true; + break; + } + } while (time_after(dw_jiffies, jiffies)); + + if (!is_ready) { + DRM_INFO("phystopstateclklane is not ready! MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n", + tmp); + } + + /*************************Configure the DPHY end*************************/ + + /* phy_stop_wait_time*/ + set_reg(mipi_dsi_base + MIPIDSI_PHY_IF_CFG_OFFSET, dsi->phy.phy_stop_wait_time, 8, 8); + + /*--------------configuring the DPI packet transmission----------------*/ + /* + ** 2. Configure the DPI Interface: + ** This defines how the DPI interface interacts with the controller. + */ + set_reg(mipi_dsi_base + MIPIDSI_DPI_VCID_OFFSET, mipi->vc, 2, 0); + set_reg(mipi_dsi_base + MIPIDSI_DPI_COLOR_CODING_OFFSET, mipi->color_mode, 4, 0); + + set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, dsi->ldi.data_en_plr, 1, 0); + set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, dsi->ldi.vsync_plr, 1, 1); + set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, dsi->ldi.hsync_plr, 1, 2); + set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, 0x0, 1, 3); + set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, 0x0, 1, 4); + + /* + ** 3. Select the Video Transmission Mode: + ** This defines how the processor requires the video line to be + ** transported through the DSI link. + */ + /* video mode: low power mode*/ + set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x3f, 6, 8); + /* set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x0, 1, 14); */ + + /* TODO: fix blank display bug when set backlight*/ + set_reg(mipi_dsi_base + MIPIDSI_DPI_LP_CMD_TIM_OFFSET, 0x4, 8, 16); + /* video mode: send read cmd by lp mode*/ + set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x1, 1, 15); + + set_reg(mipi_dsi_base + MIPIDSI_VID_PKT_SIZE_OFFSET, rect.w, 14, 0); + + /* burst mode*/ + dsi_set_burst_mode(mipi_dsi_base, dsi->client[id].mode_flags); + /* for dsi read, BTA enable*/ + set_reg(mipi_dsi_base + MIPIDSI_PCKHDL_CFG_OFFSET, 0x1, 1, 2); + + /* + ** 4. Define the DPI Horizontal timing configuration: + ** + ** Hsa_time = HSA*(PCLK period/Clk Lane Byte Period); + ** Hbp_time = HBP*(PCLK period/Clk Lane Byte Period); + ** Hline_time = (HSA+HBP+HACT+HFP)*(PCLK period/Clk Lane Byte Period); + */ + pixel_clk = dsi->cur_mode.clock * 1000; + /*htot = dsi->cur_mode.htotal;*/ + /*vtot = dsi->cur_mode.vtotal;*/ + dsi->ldi.h_front_porch = dsi->cur_mode.hsync_start - dsi->cur_mode.hdisplay; + dsi->ldi.h_back_porch = dsi->cur_mode.htotal - dsi->cur_mode.hsync_end; + dsi->ldi.h_pulse_width = dsi->cur_mode.hsync_end - dsi->cur_mode.hsync_start; + dsi->ldi.v_front_porch = dsi->cur_mode.vsync_start - dsi->cur_mode.vdisplay; + dsi->ldi.v_back_porch = dsi->cur_mode.vtotal - dsi->cur_mode.vsync_end; + dsi->ldi.v_pulse_width = dsi->cur_mode.vsync_end - dsi->cur_mode.vsync_start; + if (dsi->ldi.v_pulse_width > 15) { + DRM_DEBUG_DRIVER("vsw exceeded 15\n"); + dsi->ldi.v_pulse_width = 15; + } + hsa_time = dsi->ldi.h_pulse_width * dsi->phy.lane_byte_clk / pixel_clk; + hbp_time = dsi->ldi.h_back_porch * dsi->phy.lane_byte_clk / pixel_clk; + hline_time = ROUND1((dsi->ldi.h_pulse_width + dsi->ldi.h_back_porch + + rect.w + dsi->ldi.h_front_porch) * dsi->phy.lane_byte_clk, pixel_clk); + + DRM_INFO("hsa_time=%d, hbp_time=%d, hline_time=%d\n", + hsa_time, hbp_time, hline_time); + DRM_INFO("lane_byte_clk=%llu, pixel_clk=%llu\n", + dsi->phy.lane_byte_clk, pixel_clk); + set_reg(mipi_dsi_base + MIPIDSI_VID_HSA_TIME_OFFSET, hsa_time, 12, 0); + set_reg(mipi_dsi_base + MIPIDSI_VID_HBP_TIME_OFFSET, hbp_time, 12, 0); + set_reg(mipi_dsi_base + MIPIDSI_VID_HLINE_TIME_OFFSET, hline_time, 15, 0); + + /* Define the Vertical line configuration*/ + set_reg(mipi_dsi_base + MIPIDSI_VID_VSA_LINES_OFFSET, dsi->ldi.v_pulse_width, 10, 0); + set_reg(mipi_dsi_base + MIPIDSI_VID_VBP_LINES_OFFSET, dsi->ldi.v_back_porch, 10, 0); + set_reg(mipi_dsi_base + MIPIDSI_VID_VFP_LINES_OFFSET, dsi->ldi.v_front_porch, 10, 0); + set_reg(mipi_dsi_base + MIPIDSI_VID_VACTIVE_LINES_OFFSET, rect.h, 14, 0); + set_reg(mipi_dsi_base + MIPIDSI_TO_CNT_CFG_OFFSET, 0x7FF, 16, 0); + + /* Configure core's phy parameters*/ + set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET, dsi->phy.clk_lane_lp2hs_time, 10, 0); + set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET, dsi->phy.clk_lane_hs2lp_time, 10, 16); + + set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_RD_CFG_OFFSET, 0x7FFF, 15, 0); + 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); + + /* Waking up Core*/ + set_reg(mipi_dsi_base + MIPIDSI_PWR_UP_OFFSET, 0x1, 1, 0); +} + +static void dsi_encoder_disable(struct drm_encoder *encoder) +{ + struct dw_dsi *dsi = encoder_to_dsi(encoder); + struct dsi_hw_ctx *ctx = dsi->ctx; + void __iomem *base = ctx->base; + + if (!dsi->enable) + return; + + dw_dsi_set_mode(dsi, DSI_COMMAND_MODE); + /* turn off panel's backlight */ + if (dsi->panel && drm_panel_disable(dsi->panel)) + DRM_ERROR("failed to disable panel\n"); + + /* turn off panel */ + if (dsi->panel && drm_panel_unprepare(dsi->panel)) + DRM_ERROR("failed to unprepare panel\n"); + + writel(0, base + PWR_UP); + writel(0, base + LPCLK_CTRL); + writel(0, base + PHY_RSTZ); + clk_disable_unprepare(ctx->dss_dphy0_ref_clk); + clk_disable_unprepare(ctx->dss_dphy0_cfg_clk); + clk_disable_unprepare(ctx->dss_pclk_dsi0_clk); + + dsi->enable = false; +} + +static int mipi_dsi_on_sub1(struct dw_dsi *dsi, char __iomem *mipi_dsi_base) +{ + WARN_ON(!mipi_dsi_base); + + /* mipi init */ + dsi_mipi_init(dsi, mipi_dsi_base); + DRM_INFO("dsi_mipi_init ok\n"); + /* switch to cmd mode */ + set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x1, 1, 0); + /* cmd mode: low power mode */ + set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0x7f, 7, 8); + set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0xf, 4, 16); + set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0x1, 1, 24); + /* disable generate High Speed clock */ + /* delete? */ + set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x0, 1, 0); + + return 0; +} + +static int mipi_dsi_on_sub2(struct dw_dsi *dsi, char __iomem *mipi_dsi_base) +{ + WARN_ON(!mipi_dsi_base); + + /* switch to video mode */ + set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x0, 1, 0); + + /* enable EOTP TX */ + set_reg(mipi_dsi_base + MIPIDSI_PCKHDL_CFG_OFFSET, 0x1, 1, 0); + + /* enable generate High Speed clock, continue clock */ + set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x1, 2, 0); + + return 0; +} + +static void dsi_encoder_enable(struct drm_encoder *encoder) +{ + struct dw_dsi *dsi = encoder_to_dsi(encoder); + struct dsi_hw_ctx *ctx = dsi->ctx; + int ret; + + if (dsi->enable) + return; + + ret = clk_prepare_enable(ctx->dss_dphy0_ref_clk); + if (ret) { + DRM_ERROR("fail to enable dss_dphy0_ref_clk: %d\n", ret); + return; + } + + ret = clk_prepare_enable(ctx->dss_dphy0_cfg_clk); + if (ret) { + DRM_ERROR("fail to enable dss_dphy0_cfg_clk: %d\n", ret); + return; + } + + ret = clk_prepare_enable(ctx->dss_pclk_dsi0_clk); + if (ret) { + DRM_ERROR("fail to enable dss_pclk_dsi0_clk: %d\n", ret); + return; + } + + mipi_dsi_on_sub1(dsi, ctx->base); + + mipi_dsi_on_sub2(dsi, ctx->base); + + /* turn on panel */ + if (dsi->panel && drm_panel_prepare(dsi->panel)) + DRM_ERROR("failed to prepare panel\n"); + + /*dw_dsi_set_mode(dsi, DSI_VIDEO_MODE);*/ + + /* turn on panel's back light */ + if (dsi->panel && drm_panel_enable(dsi->panel)) + DRM_ERROR("failed to enable panel\n"); + + dsi->enable = true; +} + +static void dsi_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adj_mode) +{ + struct dw_dsi *dsi = encoder_to_dsi(encoder); + + drm_mode_copy(&dsi->cur_mode, adj_mode); +} + +static int dsi_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + /* do nothing */ + return 0; +} + +static const struct drm_encoder_helper_funcs dw_encoder_helper_funcs = { + .atomic_check = dsi_encoder_atomic_check, + .mode_set = dsi_encoder_mode_set, + .enable = dsi_encoder_enable, + .disable = dsi_encoder_disable +}; + +static const struct drm_encoder_funcs dw_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +static int dw_drm_encoder_init(struct device *dev, + struct drm_device *drm_dev, + struct drm_encoder *encoder) +{ + int ret; + u32 crtc_mask = drm_of_find_possible_crtcs(drm_dev, dev->of_node); + + if (!crtc_mask) { + DRM_ERROR("failed to find crtc mask\n"); + return -EINVAL; + } + + encoder->possible_crtcs = crtc_mask; + ret = drm_encoder_init(drm_dev, encoder, &dw_encoder_funcs, + DRM_MODE_ENCODER_DSI); + if (ret) { + DRM_ERROR("failed to init dsi encoder\n"); + return ret; + } + + drm_encoder_helper_add(encoder, &dw_encoder_helper_funcs); + + return 0; +} + +static int dsi_host_attach(struct mipi_dsi_host *host, + struct mipi_dsi_device *mdsi) +{ + struct dw_dsi *dsi = host_to_dsi(host); + u32 id = mdsi->channel >= 1 ? OUT_PANEL : OUT_HDMI; + + if (mdsi->lanes < 1 || mdsi->lanes > 4) { + DRM_ERROR("dsi device params invalid\n"); + return -EINVAL; + } + + dsi->client[id].lanes = mdsi->lanes; + dsi->client[id].format = mdsi->format; + dsi->client[id].mode_flags = mdsi->mode_flags; + dsi->client[id].phy_clock = mdsi->phy_clock; + + DRM_INFO("host attach, client name=[%s], id=%d\n", mdsi->name, id); + + return 0; +} + +static int dsi_host_detach(struct mipi_dsi_host *host, + struct mipi_dsi_device *mdsi) +{ + /* do nothing */ + return 0; +} + +static int dsi_gen_pkt_hdr_write(void __iomem *base, u32 val) +{ + u32 status; + int ret; + + ret = readx_poll_timeout(readl, base + CMD_PKT_STATUS, status, + !(status & GEN_CMD_FULL), 1000, + CMD_PKT_STATUS_TIMEOUT_US); + if (ret < 0) { + DRM_ERROR("failed to get available command FIFO\n"); + return ret; + } + + writel(val, base + GEN_HDR); + + ret = readx_poll_timeout(readl, base + CMD_PKT_STATUS, status, + status & (GEN_CMD_EMPTY | GEN_PLD_W_EMPTY), + 1000, CMD_PKT_STATUS_TIMEOUT_US); + if (ret < 0) { + DRM_ERROR("failed to write command FIFO\n"); + return ret; + } + + return 0; +} + +static int dsi_dcs_short_write(void __iomem *base, + const struct mipi_dsi_msg *msg) +{ + const u16 *tx_buf = msg->tx_buf; + u32 val = GEN_HDATA(*tx_buf) | GEN_HTYPE(msg->type); + + if (msg->tx_len > 2) { + DRM_ERROR("too long tx buf length %zu for short write\n", + msg->tx_len); + return -EINVAL; + } + + return dsi_gen_pkt_hdr_write(base, val); +} + +static int dsi_dcs_long_write(void __iomem *base, + const struct mipi_dsi_msg *msg) +{ + const u32 *tx_buf = msg->tx_buf; + int len = msg->tx_len, pld_data_bytes = sizeof(*tx_buf), ret; + u32 val = GEN_HDATA(msg->tx_len) | GEN_HTYPE(msg->type); + u32 remainder = 0; + u32 status; + + if (msg->tx_len < 3) { + DRM_ERROR("wrong tx buf length %zu for long write\n", + msg->tx_len); + return -EINVAL; + } + + while (DIV_ROUND_UP(len, pld_data_bytes)) { + if (len < pld_data_bytes) { + memcpy(&remainder, tx_buf, len); + writel(remainder, base + GEN_PLD_DATA); + len = 0; + } else { + writel(*tx_buf, base + GEN_PLD_DATA); + tx_buf++; + len -= pld_data_bytes; + } + + ret = readx_poll_timeout(readl, base + CMD_PKT_STATUS, + status, !(status & GEN_PLD_W_FULL), 1000, + CMD_PKT_STATUS_TIMEOUT_US); + if (ret < 0) { + DRM_ERROR("failed to get available write payload FIFO\n"); + return ret; + } + } + + return dsi_gen_pkt_hdr_write(base, val); +} + +static ssize_t dsi_host_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) +{ + struct dw_dsi *dsi = host_to_dsi(host); + struct dsi_hw_ctx *ctx = dsi->ctx; + void __iomem *base = ctx->base; + int ret; + + switch (msg->type) { + case MIPI_DSI_DCS_SHORT_WRITE: + case MIPI_DSI_DCS_SHORT_WRITE_PARAM: + case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: + ret = dsi_dcs_short_write(base, msg); + break; + case MIPI_DSI_DCS_LONG_WRITE: + ret = dsi_dcs_long_write(base, msg); + break; + default: + DRM_ERROR("unsupported message type\n"); + ret = -EINVAL; + } + + return ret; +} + +static const struct mipi_dsi_host_ops dsi_host_ops = { + .attach = dsi_host_attach, + .detach = dsi_host_detach, + .transfer = dsi_host_transfer, +}; + +static int dsi_host_init(struct device *dev, struct dw_dsi *dsi) +{ + struct mipi_dsi_host *host = &dsi->host; + struct mipi_panel_info *mipi = &dsi->mipi; + int ret; + + host->dev = dev; + host->ops = &dsi_host_ops; + + mipi->max_tx_esc_clk = 10; + mipi->vc = 0; + mipi->color_mode = DSI_24BITS_1; + mipi->clk_post_adjust = 120; + mipi->clk_pre_adjust= 0; + mipi->clk_t_hs_prepare_adjust= 0; + mipi->clk_t_lpx_adjust= 0; + mipi->clk_t_hs_trial_adjust= 0; + mipi->clk_t_hs_exit_adjust= 0; + mipi->clk_t_hs_zero_adjust= 0; + + dsi->ldi.data_en_plr = 0; + dsi->ldi.vsync_plr = 0; + dsi->ldi.hsync_plr = 0; + + ret = mipi_dsi_host_register(host); + if (ret) { + DRM_ERROR("failed to register dsi host\n"); + return ret; + } + + return 0; +} + +static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi) +{ + struct drm_encoder *encoder = &dsi->encoder; + struct drm_bridge *bridge = dsi->bridge; + int ret; + + /* associate the bridge to dsi encoder */ + bridge->encoder = encoder; + + ret = drm_bridge_attach(dev, bridge); + if (ret) { + DRM_ERROR("failed to attach external bridge\n"); + return ret; + } + + return 0; +} + +static int dsi_connector_get_modes(struct drm_connector *connector) +{ + struct dw_dsi *dsi = connector_to_dsi(connector); + + return drm_panel_get_modes(dsi->panel); +} + +static enum drm_mode_status +dsi_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + enum drm_mode_status mode_status = MODE_OK; + + return mode_status; +} + +static struct drm_encoder * +dsi_connector_best_encoder(struct drm_connector *connector) +{ + struct dw_dsi *dsi = connector_to_dsi(connector); + + return &dsi->encoder; +} + +static struct drm_connector_helper_funcs dsi_connector_helper_funcs = { + .get_modes = dsi_connector_get_modes, + .mode_valid = dsi_connector_mode_valid, + .best_encoder = dsi_connector_best_encoder, +}; + +static enum drm_connector_status +dsi_connector_detect(struct drm_connector *connector, bool force) +{ + struct dw_dsi *dsi = connector_to_dsi(connector); + enum drm_connector_status status; + + status = dsi->cur_client == OUT_PANEL ? connector_status_connected : + connector_status_disconnected; + + return status; +} + +static void dsi_connector_destroy(struct drm_connector *connector) +{ + drm_connector_unregister(connector); + drm_connector_cleanup(connector); +} + +static struct drm_connector_funcs dsi_atomic_connector_funcs = { + .dpms = drm_atomic_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = dsi_connector_detect, + .destroy = dsi_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int dsi_connector_init(struct drm_device *dev, struct dw_dsi *dsi) +{ + struct drm_encoder *encoder = &dsi->encoder; + struct drm_connector *connector = &dsi->connector; + int ret; + + connector->polled = DRM_CONNECTOR_POLL_HPD; + drm_connector_helper_add(connector, + &dsi_connector_helper_funcs); + + ret = drm_connector_init(dev, &dsi->connector, + &dsi_atomic_connector_funcs, + DRM_MODE_CONNECTOR_DSI); + if (ret) + return ret; + + ret = drm_mode_connector_attach_encoder(connector, encoder); + if (ret) + return ret; + + ret = drm_panel_attach(dsi->panel, connector); + if (ret) + return ret; + + DRM_INFO("connector init\n"); + return 0; +} +static int dsi_bind(struct device *dev, struct device *master, void *data) +{ + struct dsi_data *ddata = dev_get_drvdata(dev); + struct dw_dsi *dsi = &ddata->dsi; + struct drm_device *drm_dev = data; + int ret; + + ret = dw_drm_encoder_init(dev, drm_dev, &dsi->encoder); + if (ret) + return ret; + + if (dsi->bridge) { + ret = dsi_bridge_init(drm_dev, dsi); + if (ret) + return ret; + } + + if (dsi->panel) { + ret = dsi_connector_init(drm_dev, dsi); + if (ret) + return ret; + } + + return 0; +} + +static void dsi_unbind(struct device *dev, struct device *master, void *data) +{ + /* do nothing */ +} + +static const struct component_ops dsi_ops = { + .bind = dsi_bind, + .unbind = dsi_unbind, +}; + +static int dsi_parse_bridge_endpoint(struct dw_dsi *dsi, + struct device_node *endpoint) +{ + struct device_node *bridge_node; + struct drm_bridge *bridge; + + bridge_node = of_graph_get_remote_port_parent(endpoint); + if (!bridge_node) { + DRM_ERROR("no valid bridge node\n"); + return -ENODEV; + } + of_node_put(bridge_node); + + bridge = of_drm_find_bridge(bridge_node); + if (!bridge) { + DRM_INFO("wait for external HDMI bridge driver.\n"); + return -EPROBE_DEFER; + } + dsi->bridge = bridge; + + return 0; +} + +static int dsi_parse_panel_endpoint(struct dw_dsi *dsi, + struct device_node *endpoint) +{ + struct device_node *panel_node; + struct drm_panel *panel; + + panel_node = of_graph_get_remote_port_parent(endpoint); + if (!panel_node) { + DRM_ERROR("no valid panel node\n"); + return -ENODEV; + } + of_node_put(panel_node); + + panel = of_drm_find_panel(panel_node); + if (!panel) { + DRM_DEBUG_DRIVER("skip this panel endpoint.\n"); + return 0; + } + dsi->panel = panel; + + return 0; +} + +static int dsi_parse_endpoint(struct dw_dsi *dsi, + struct device_node *np, + enum dsi_output_client client) +{ + struct device_node *ep_node; + struct of_endpoint ep; + int ret = 0; + + if (client == OUT_MAX) + return -EINVAL; + + for_each_endpoint_of_node(np, ep_node) { + ret = of_graph_parse_endpoint(ep_node, &ep); + if (ret) { + of_node_put(ep_node); + return ret; + } + + /* skip dsi input port, port == 0 is input port */ + if (ep.port == 0) + continue; + + /* parse bridge endpoint */ + if (client == OUT_HDMI) { + if (ep.id == 0) { + ret = dsi_parse_bridge_endpoint(dsi, ep_node); + if (dsi->bridge) + break; + } + } else { /* parse panel endpoint */ + if (ep.id > 0) { + ret = dsi_parse_panel_endpoint(dsi, ep_node); + if (dsi->panel) + break; + } + } + + if (ret) { + of_node_put(ep_node); + return ret; + } + } + + if (!dsi->bridge && !dsi->panel) { + DRM_ERROR("at least one bridge or panel node is required\n"); + return -ENODEV; + } + + return 0; +} + +static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi) +{ + struct dsi_hw_ctx *ctx = dsi->ctx; + int ret = 0; + struct device_node *np = NULL; + + 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; + } + + ctx->base = of_iomap(np, 0); + if (!(ctx->base)) { + DRM_ERROR ("failed to get base resource.\n"); + return -ENXIO; + } + + 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; + } + + 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; + + /*dis-reset*/ + /*ip_reset_dis_dsi0, ip_reset_dis_dsi1*/ + outp32(ctx->peri_crg_base + PERRSTDIS3, 0x30000000); + + ctx->dss_dphy0_ref_clk = devm_clk_get(&pdev->dev, "clk_txdphy0_ref"); + if (IS_ERR(ctx->dss_dphy0_ref_clk)) { + DRM_ERROR("failed to get dss_dphy0_ref_clk clock\n"); + return PTR_ERR(ctx->dss_dphy0_ref_clk); + } + + ret = clk_set_rate(ctx->dss_dphy0_ref_clk, DEFAULT_MIPI_CLK_RATE); + if (ret < 0) { + DRM_ERROR("dss_dphy0_ref_clk clk_set_rate(%lu) failed, error=%d!\n", + DEFAULT_MIPI_CLK_RATE, ret); + return -EINVAL; + } + + DRM_DEBUG("dss_dphy0_ref_clk:[%lu]->[%lu].\n", + DEFAULT_MIPI_CLK_RATE, clk_get_rate(ctx->dss_dphy0_ref_clk)); + + ctx->dss_dphy0_cfg_clk = devm_clk_get(&pdev->dev, "clk_txdphy0_cfg"); + if (IS_ERR(ctx->dss_dphy0_cfg_clk)) { + DRM_ERROR("failed to get dss_dphy0_cfg_clk clock\n"); + return PTR_ERR(ctx->dss_dphy0_cfg_clk); + } + + ret = clk_set_rate(ctx->dss_dphy0_cfg_clk, DEFAULT_MIPI_CLK_RATE); + if (ret < 0) { + DRM_ERROR("dss_dphy0_cfg_clk clk_set_rate(%lu) failed, error=%d!\n", + DEFAULT_MIPI_CLK_RATE, ret); + return -EINVAL; + } + + DRM_DEBUG("dss_dphy0_cfg_clk:[%lu]->[%lu].\n", + DEFAULT_MIPI_CLK_RATE, clk_get_rate(ctx->dss_dphy0_cfg_clk)); + + ctx->dss_pclk_dsi0_clk = devm_clk_get(&pdev->dev, "pclk_dsi0"); + if (IS_ERR(ctx->dss_pclk_dsi0_clk)) { + DRM_ERROR("failed to get dss_pclk_dsi0_clk clock\n"); + return PTR_ERR(ctx->dss_pclk_dsi0_clk); + } + + return 0; +} + +static int dsi_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct dsi_data *data; + struct dw_dsi *dsi; + struct dsi_hw_ctx *ctx; + int ret; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) { + DRM_ERROR("failed to allocate dsi data.\n"); + return -ENOMEM; + } + dsi = &data->dsi; + ctx = &data->ctx; + dsi->ctx = ctx; + + /* parse HDMI bridge endpoint */ + ret = dsi_parse_endpoint(dsi, np, OUT_HDMI); + if (ret) + return ret; + + ret = dsi_host_init(dev, dsi); + if (ret) + return ret; + + /* parse panel endpoint */ + ret = dsi_parse_endpoint(dsi, np, OUT_PANEL); + if (ret) + goto err_host_unregister; + + ret = dsi_parse_dt(pdev, dsi); + if (ret) + goto err_host_unregister; + + platform_set_drvdata(pdev, data); + + ret = component_add(dev, &dsi_ops); + if (ret) + goto err_host_unregister; + + return 0; + +err_host_unregister: + mipi_dsi_host_unregister(&dsi->host); + return ret; +} + +static int dsi_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &dsi_ops); + + return 0; +} + +static const struct of_device_id dsi_of_match[] = { + {.compatible = "hisilicon,hi3660-dsi"}, + { } +}; +MODULE_DEVICE_TABLE(of, dsi_of_match); + +static struct platform_driver dsi_driver = { + .probe = dsi_probe, + .remove = dsi_remove, + .driver = { + .name = "dw-dsi", + .of_match_table = dsi_of_match, + }, +}; + +module_platform_driver(dsi_driver); + +MODULE_DESCRIPTION("DesignWare MIPI DSI Host Controller v1.02 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/hikey9xx/gpu/dw_dsi_reg.h b/drivers/staging/hikey9xx/gpu/dw_dsi_reg.h new file mode 100644 index 000000000000..00fac1f35265 --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/dw_dsi_reg.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2016 Linaro Limited. + * Copyright (c) 2014-2016 Hisilicon Limited. + * + * 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. + * + */ + +#ifndef __DW_DSI_REG_H__ +#define __DW_DSI_REG_H__ + +#define MASK(x) (BIT(x) - 1) +#define DEFAULT_MAX_TX_ESC_CLK (10 * 1000000UL) +/* + * regs + */ +#define PWR_UP 0x04 /* Core power-up */ +#define RESET 0 +#define POWERUP BIT(0) +#define PHY_IF_CFG 0xA4 /* D-PHY interface configuration */ +#define CLKMGR_CFG 0x08 /* the internal clock dividers */ +#define PHY_RSTZ 0xA0 /* D-PHY reset control */ +#define PHY_ENABLECLK BIT(2) +#define PHY_UNRSTZ BIT(1) +#define PHY_UNSHUTDOWNZ BIT(0) +#define PHY_TST_CTRL0 0xB4 /* D-PHY test interface control 0 */ +#define PHY_TST_CTRL1 0xB8 /* D-PHY test interface control 1 */ +#define CLK_TLPX 0x10 +#define CLK_THS_PREPARE 0x11 +#define CLK_THS_ZERO 0x12 +#define CLK_THS_TRAIL 0x13 +#define CLK_TWAKEUP 0x14 +#define DATA_TLPX(x) (0x20 + ((x) << 4)) +#define DATA_THS_PREPARE(x) (0x21 + ((x) << 4)) +#define DATA_THS_ZERO(x) (0x22 + ((x) << 4)) +#define DATA_THS_TRAIL(x) (0x23 + ((x) << 4)) +#define DATA_TTA_GO(x) (0x24 + ((x) << 4)) +#define DATA_TTA_GET(x) (0x25 + ((x) << 4)) +#define DATA_TWAKEUP(x) (0x26 + ((x) << 4)) +#define PHY_CFG_I 0x60 +#define PHY_CFG_PLL_I 0x63 +#define PHY_CFG_PLL_II 0x64 +#define PHY_CFG_PLL_III 0x65 +#define PHY_CFG_PLL_IV 0x66 +#define PHY_CFG_PLL_V 0x67 +#define DPI_COLOR_CODING 0x10 /* DPI color coding */ +#define DPI_CFG_POL 0x14 /* DPI polarity configuration */ +#define VID_HSA_TIME 0x48 /* Horizontal Sync Active time */ +#define VID_HBP_TIME 0x4C /* Horizontal Back Porch time */ +#define VID_HLINE_TIME 0x50 /* Line time */ +#define VID_VSA_LINES 0x54 /* Vertical Sync Active period */ +#define VID_VBP_LINES 0x58 /* Vertical Back Porch period */ +#define VID_VFP_LINES 0x5C /* Vertical Front Porch period */ +#define VID_VACTIVE_LINES 0x60 /* Vertical resolution */ +#define VID_PKT_SIZE 0x3C /* Video packet size */ +#define VID_MODE_CFG 0x38 /* Video mode configuration */ +#define GEN_HDR 0x6c +#define GEN_HDATA(data) (((data) & 0xffff) << 8) +#define GEN_HDATA_MASK (0xffff << 8) +#define GEN_HTYPE(type) (((type) & 0xff) << 0) +#define GEN_HTYPE_MASK 0xff +#define GEN_PLD_DATA 0x70 +#define CMD_PKT_STATUS 0x74 +#define GEN_CMD_EMPTY BIT(0) +#define GEN_CMD_FULL BIT(1) +#define GEN_PLD_W_EMPTY BIT(2) +#define GEN_PLD_W_FULL BIT(3) +#define GEN_PLD_R_EMPTY BIT(4) +#define GEN_PLD_R_FULL BIT(5) +#define GEN_RD_CMD_BUSY BIT(6) +#define CMD_MODE_CFG 0x68 +#define MAX_RD_PKT_SIZE_LP BIT(24) +#define DCS_LW_TX_LP BIT(19) +#define DCS_SR_0P_TX_LP BIT(18) +#define DCS_SW_1P_TX_LP BIT(17) +#define DCS_SW_0P_TX_LP BIT(16) +#define GEN_LW_TX_LP BIT(14) +#define GEN_SR_2P_TX_LP BIT(13) +#define GEN_SR_1P_TX_LP BIT(12) +#define GEN_SR_0P_TX_LP BIT(11) +#define GEN_SW_2P_TX_LP BIT(10) +#define GEN_SW_1P_TX_LP BIT(9) +#define GEN_SW_0P_TX_LP BIT(8) +#define EN_ACK_RQST BIT(1) +#define EN_TEAR_FX BIT(0) +#define CMD_MODE_ALL_LP (MAX_RD_PKT_SIZE_LP | \ + DCS_LW_TX_LP | \ + DCS_SR_0P_TX_LP | \ + DCS_SW_1P_TX_LP | \ + DCS_SW_0P_TX_LP | \ + GEN_LW_TX_LP | \ + GEN_SR_2P_TX_LP | \ + GEN_SR_1P_TX_LP | \ + GEN_SR_0P_TX_LP | \ + GEN_SW_2P_TX_LP | \ + GEN_SW_1P_TX_LP | \ + GEN_SW_0P_TX_LP) +#define PHY_TMR_CFG 0x9C /* Data lanes timing configuration */ +#define BTA_TO_CNT 0x8C /* Response timeout definition */ +#define PHY_TMR_LPCLK_CFG 0x98 /* clock lane timing configuration */ +#define CLK_DATA_TMR_CFG 0xCC +#define LPCLK_CTRL 0x94 /* Low-power in clock lane */ +#define PHY_TXREQUESTCLKHS BIT(0) +#define MODE_CFG 0x34 /* Video or Command mode selection */ +#define PHY_STATUS 0xB0 /* D-PHY PPI status interface */ + +#define PHY_STOP_WAIT_TIME 0x30 +#define CMD_PKT_STATUS_TIMEOUT_US 20000 + +/* + * regs relevant enum + */ +enum dpi_color_coding { + DSI_24BITS_1 = 5, +}; + +enum dsi_video_mode_type { + DSI_NON_BURST_SYNC_PULSES = 0, + DSI_NON_BURST_SYNC_EVENTS, + DSI_BURST_SYNC_PULSES_1, + DSI_BURST_SYNC_PULSES_2 +}; + +enum dsi_work_mode { + DSI_VIDEO_MODE = 0, + DSI_COMMAND_MODE +}; + +/* + * Register Write/Read Helper functions + */ +static inline void dw_update_bits(void __iomem *addr, u32 bit_start, + u32 mask, u32 val) +{ + u32 tmp, orig; + + orig = readl(addr); + tmp = orig & ~(mask << bit_start); + tmp |= (val & mask) << bit_start; + writel(tmp, addr); +} + +#endif /* __DW_DRM_DSI_H__ */ diff --git a/drivers/staging/hikey9xx/gpu/kirin_dpe_reg.h b/drivers/staging/hikey9xx/gpu/kirin_dpe_reg.h new file mode 100644 index 000000000000..61af8ef81878 --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/kirin_dpe_reg.h @@ -0,0 +1,3114 @@ +/* + * Copyright (c) 2016 Linaro Limited. + * Copyright (c) 2014-2016 Hisilicon Limited. + * + * 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. + * + */ + +#ifndef __KIRIN_DPE_REG_H__ +#define __KIRIN_DPE_REG_H__ + +#include <linux/delay.h> +#include <linux/string.h> +#include <linux/platform_device.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/wait.h> +#include <linux/bug.h> + +#include <linux/ion.h> +#include <linux/hisi/hisi_ion.h> + +/******************************************************************************* +** +*/ +enum dss_chn_idx { + DSS_RCHN_NONE = -1, + 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_CHN_MAX, + + DSS_RCHN_V2 = DSS_CHN_MAX, /*for copybit, only supported in chicago*/ + DSS_WCHN_W2, + + DSS_COPYBIT_MAX, +}; + +enum dss_channel { + DSS_CH1 = 0, /* channel 1 for primary plane */ + DSS_CH_NUM +}; + +#define PRIMARY_CH DSS_CH1 /* primary plane */ + +typedef struct dss_rect { + s32 x; + s32 y; + s32 w; + s32 h; +} dss_rect_t; + +typedef struct dss_rect_ltrb { + s32 left; + s32 top; + s32 right; + s32 bottom; +} dss_rect_ltrb_t; + +enum { + DSI_1_LANES = 0, + DSI_2_LANES, + DSI_3_LANES, + DSI_4_LANES, +}; + +enum dss_ovl_idx { + DSS_OVL0 = 0, + DSS_OVL1, + DSS_OVL2, + DSS_OVL3, + DSS_OVL_IDX_MAX, +}; + +#define DSS_WCH_MAX (2) + +typedef struct dss_img { + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t bpp; /* bytes per pixel */ + uint32_t buf_size; + uint32_t stride; + uint32_t stride_plane1; + uint32_t stride_plane2; + uint64_t phy_addr; + uint64_t vir_addr; + uint32_t offset_plane1; + uint32_t offset_plane2; + + uint64_t afbc_header_addr; + uint64_t afbc_payload_addr; + uint32_t afbc_header_stride; + uint32_t afbc_payload_stride; + uint32_t afbc_scramble_mode; + uint32_t mmbuf_base; + uint32_t mmbuf_size; + + uint32_t mmu_enable; + uint32_t csc_mode; + uint32_t secure_mode; + int32_t shared_fd; + uint32_t reserved0; +} dss_img_t; + +typedef struct drm_dss_layer { + dss_img_t img; + dss_rect_t src_rect; + dss_rect_t src_rect_mask; + dss_rect_t dst_rect; + uint32_t transform; + int32_t blending; + uint32_t glb_alpha; + uint32_t color; /* background color or dim color */ + int32_t layer_idx; + int32_t chn_idx; + uint32_t need_cap; + int32_t acquire_fence; +} drm_dss_layer_t; + + +/******************************************************************************* +** +*/ +#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 +#define DSS_DSI_ADDR (DSS_ADDR + 0x01000) +#define DSS_LDI_ADDR (DSS_ADDR + 0x7d000) +#define PMC_BASE (0xFFF31000) +#define PERI_CRG_BASE (0xFFF35000) +#define SCTRL_BASE (0xFFF0A000) + +#define GPIO_LCD_POWER_1V2 (54) +#define GPIO_LCD_STANDBY (67) +#define GPIO_LCD_RESETN (65) +#define GPIO_LCD_GATING (60) +#define GPIO_LCD_PCLK_GATING (58) +#define GPIO_LCD_REFCLK_GATING (59) +#define GPIO_LCD_SPICS (168) +#define GPIO_LCD_DRV_EN (73) + +#define GPIO_PG_SEL_A (72) +#define GPIO_TX_RX_A (74) +#define GPIO_PG_SEL_B (76) +#define GPIO_TX_RX_B (78) + +/******************************************************************************* + ** + */ +#define CRGPERI_PLL0_CLK_RATE (1600000000UL) +#define CRGPERI_PLL2_CLK_RATE (960000000UL) +#define CRGPERI_PLL3_CLK_RATE (1600000000UL) + +#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 MMBUF_SIZE_MAX (288 * 1024) +#define HISI_DSS_CMDLIST_MAX (16) +#define HISI_DSS_CMDLIST_IDXS_MAX (0xFFFF) +#define HISI_DSS_COPYBIT_CMDLIST_IDXS (0xC000) +#define HISI_DSS_DPP_MAX_SUPPORT_BIT (0x7ff) +#define HISIFB_DSS_PLATFORM_TYPE (FB_ACCEL_HI366x | FB_ACCEL_PLATFORM_TYPE_ASIC) + +#define DSS_MIF_SMMU_SMRX_IDX_STEP (16) +#define CRG_PERI_DIS3_DEFAULT_VAL (0x0002F000) +#define SCF_LINE_BUF (2560) +#define DSS_GLB_MODULE_CLK_SEL_DEFAULT_VAL (0xF0000008) +#define DSS_LDI_CLK_SEL_DEFAULT_VAL (0x00000004) +#define DSS_DBUF_MEM_CTRL_DEFAULT_VAL (0x00000008) +#define DSS_SMMU_RLD_EN0_DEFAULT_VAL (0xffffffff) +#define DSS_SMMU_RLD_EN1_DEFAULT_VAL (0xffffff8f) +#define DSS_SMMU_OUTSTANDING_VAL (0xf) +#define DSS_MIF_CTRL2_INVAL_SEL3_STRIDE_MASK (0xc) +#define DSS_AFBCE_ENC_OS_CFG_DEFAULT_VAL (0x7) +#define TUI_SEC_RCH (DSS_RCHN_V0) +#define DSS_CHN_MAX_DEFINE (DSS_COPYBIT_MAX) + +/* perf stat */ +#define DSS_DEVMEM_PERF_BASE (0xFDF10000) +#define CRG_PERIPH_APB_PERRSTSTAT0_REG (0x68) +#define CRG_PERIPH_APB_IP_RST_PERF_STAT_BIT (18) +#define PERF_SAMPSTOP_REG (0x10) +#define DEVMEM_PERF_SIZE (0x100) + +/* + * DSS Registers +*/ + +/* MACROS */ +#define DSS_WIDTH(width) ((width) - 1) +#define DSS_HEIGHT(height) ((height) - 1) + +#define RES_540P (960 * 540) +#define RES_720P (1280 * 720) +#define RES_1080P (1920 * 1080) +#define RES_1200P (1920 * 1200) +#define RES_1440P (2560 * 1440) +#define RES_1600P (2560 * 1600) +#define RES_4K_PHONE (3840 * 2160) +#define RES_4K_PAD (3840 * 2400) + +#define DFC_MAX_CLIP_NUM (31) + +/* for DFS */ +/* 1480 * 144bits */ +#define DFS_TIME (80) +#define DFS_TIME_MIN (50) +#define DFS_TIME_MIN_4K (10) +#define DBUF0_DEPTH (1408) +#define DBUF1_DEPTH (512) +#define DBUF_WIDTH_BIT (144) + +#define GET_THD_RQOS_IN(max_depth) ((max_depth) * 10 / 100) +#define GET_THD_RQOS_OUT(max_depth) ((max_depth) * 30 / 100) +#define GET_THD_WQOS_IN(max_depth) ((max_depth) * 95 / 100) +#define GET_THD_WQOS_OUT(max_depth) ((max_depth) * 70 / 100) +#define GET_THD_CG_IN(max_depth) ((max_depth) - 1) +#define GET_THD_CG_OUT(max_depth) ((max_depth) * 70 / 100) +#define GET_FLUX_REQ_IN(max_depth) ((max_depth) * 50 / 100) +#define GET_FLUX_REQ_OUT(max_depth) ((max_depth) * 90 / 100) +#define GET_THD_OTHER_DFS_CG_HOLD(max_depth) (0x20) +#define GET_THD_OTHER_WR_WAIT(max_depth) ((max_depth) * 90 / 100) + +#define GET_RDMA_ROT_HQOS_ASSERT_LEV(max_depth) ((max_depth) * 30 / 100) +#define GET_RDMA_ROT_HQOS_REMOVE_LEV(max_depth) ((max_depth) * 60 / 100) + +enum lcd_orientation { + LCD_LANDSCAPE = 0, + LCD_PORTRAIT, +}; + +enum lcd_format { + LCD_RGB888 = 0, + LCD_RGB101010, + LCD_RGB565, +}; + +enum lcd_rgb_order { + LCD_RGB = 0, + LCD_BGR, +}; + +enum dss_addr { + DSS_ADDR_PLANE0 = 0, + DSS_ADDR_PLANE1, + DSS_ADDR_PLANE2, +}; + +enum dss_transform { + DSS_TRANSFORM_NOP = 0x0, + DSS_TRANSFORM_FLIP_H = 0x01, + DSS_TRANSFORM_FLIP_V = 0x02, + DSS_TRANSFORM_ROT = 0x04, +}; + +enum dss_dfc_format { + DFC_PIXEL_FORMAT_RGB_565 = 0, + DFC_PIXEL_FORMAT_XRGB_4444, + DFC_PIXEL_FORMAT_ARGB_4444, + DFC_PIXEL_FORMAT_XRGB_5551, + DFC_PIXEL_FORMAT_ARGB_5551, + DFC_PIXEL_FORMAT_XRGB_8888, + DFC_PIXEL_FORMAT_ARGB_8888, + DFC_PIXEL_FORMAT_BGR_565, + DFC_PIXEL_FORMAT_XBGR_4444, + DFC_PIXEL_FORMAT_ABGR_4444, + DFC_PIXEL_FORMAT_XBGR_5551, + DFC_PIXEL_FORMAT_ABGR_5551, + DFC_PIXEL_FORMAT_XBGR_8888, + DFC_PIXEL_FORMAT_ABGR_8888, + + DFC_PIXEL_FORMAT_YUV444, + DFC_PIXEL_FORMAT_YVU444, + DFC_PIXEL_FORMAT_YUYV422, + DFC_PIXEL_FORMAT_YVYU422, + DFC_PIXEL_FORMAT_VYUY422, + DFC_PIXEL_FORMAT_UYVY422, +}; + +enum dss_dma_format { + DMA_PIXEL_FORMAT_RGB_565 = 0, + DMA_PIXEL_FORMAT_ARGB_4444, + DMA_PIXEL_FORMAT_XRGB_4444, + DMA_PIXEL_FORMAT_ARGB_5551, + DMA_PIXEL_FORMAT_XRGB_5551, + DMA_PIXEL_FORMAT_ARGB_8888, + DMA_PIXEL_FORMAT_XRGB_8888, + + DMA_PIXEL_FORMAT_RESERVED0, + + DMA_PIXEL_FORMAT_YUYV_422_Pkg, + DMA_PIXEL_FORMAT_YUV_420_SP_HP, + DMA_PIXEL_FORMAT_YUV_420_P_HP, + DMA_PIXEL_FORMAT_YUV_422_SP_HP, + DMA_PIXEL_FORMAT_YUV_422_P_HP, + DMA_PIXEL_FORMAT_AYUV_4444, +}; + +enum dss_buf_format { + DSS_BUF_LINEAR = 0, + DSS_BUF_TILE, +}; + +enum dss_blend_mode { + DSS_BLEND_CLEAR = 0, + DSS_BLEND_SRC, + DSS_BLEND_DST, + DSS_BLEND_SRC_OVER_DST, + DSS_BLEND_DST_OVER_SRC, + DSS_BLEND_SRC_IN_DST, + DSS_BLEND_DST_IN_SRC, + DSS_BLEND_SRC_OUT_DST, + DSS_BLEND_DST_OUT_SRC, + DSS_BLEND_SRC_ATOP_DST, + DSS_BLEND_DST_ATOP_SRC, + DSS_BLEND_SRC_XOR_DST, + DSS_BLEND_SRC_ADD_DST, + DSS_BLEND_FIX_OVER, + DSS_BLEND_FIX_PER0, + DSS_BLEND_FIX_PER1, + DSS_BLEND_FIX_PER2, + DSS_BLEND_FIX_PER3, + DSS_BLEND_FIX_PER4, + DSS_BLEND_FIX_PER5, + DSS_BLEND_FIX_PER6, + DSS_BLEND_FIX_PER7, + DSS_BLEND_FIX_PER8, + DSS_BLEND_FIX_PER9, + DSS_BLEND_FIX_PER10, + DSS_BLEND_FIX_PER11, + DSS_BLEND_FIX_PER12, + DSS_BLEND_FIX_PER13, + DSS_BLEND_FIX_PER14, + DSS_BLEND_FIX_PER15, + DSS_BLEND_FIX_PER16, + DSS_BLEND_FIX_PER17, + + DSS_BLEND_MAX, +}; + +enum dss_chn_module { + MODULE_MIF_CHN, + MODULE_AIF0_CHN, + MODULE_AIF1_CHN, + MODULE_MCTL_CHN_MUTEX, + MODULE_MCTL_CHN_FLUSH_EN, + MODULE_MCTL_CHN_OV_OEN, + MODULE_MCTL_CHN_STARTY, + MODULE_MCTL_CHN_MOD_DBG, + MODULE_DMA, + MODULE_DFC, + MODULE_SCL, + MODULE_SCL_LUT, + MODULE_ARSR2P, + MODULE_ARSR2P_LUT, + MODULE_POST_CLIP, + MODULE_PCSC, + MODULE_CSC, + MODULE_CHN_MAX, +}; + +enum dss_chn_cap { + MODULE_CAP_ROT, + MODULE_CAP_SCL, + MODULE_CAP_CSC, + MODULE_CAP_SHARPNESS_1D, + MODULE_CAP_SHARPNESS_2D, + MODULE_CAP_CE, + MODULE_CAP_AFBCD, + MODULE_CAP_AFBCE, + MODULE_CAP_YUV_PLANAR, + MODULE_CAP_YUV_SEMI_PLANAR, + MODULE_CAP_YUV_PACKAGE, + MODULE_CAP_MAX, +}; + +enum dss_ovl_module { + MODULE_OVL_BASE, + MODULE_MCTL_BASE, + MODULE_OVL_MAX, +}; + +enum dss_axi_idx { + AXI_CHN0 = 0, + AXI_CHN1, + AXI_CHN_MAX, +}; + +#define AXI0_MAX_DSS_CHN_THRESHOLD (3) +#define AXI1_MAX_DSS_CHN_THRESHOLD (3) + +#define DEFAULT_AXI_CLK_RATE0 (120 * 1000000) +#define DEFAULT_AXI_CLK_RATE1 (240 * 1000000) +#define DEFAULT_AXI_CLK_RATE2 (360 * 1000000) +#define DEFAULT_AXI_CLK_RATE3 (480 * 1000000) +#define DEFAULT_AXI_CLK_RATE4 (667 * 1000000) +#define DEFAULT_AXI_CLK_RATE5 (800 * 1000000) + +enum dss_rdma_idx { + DSS_RDMA0 = 0, + DSS_RDMA1, + DSS_RDMA2, + DSS_RDMA3, + DSS_RDMA4, + DSS_RDMA_MAX, +}; + +/******************************************************************************* + ** + */ + +#define PEREN0 (0x000) +#define PERDIS0 (0x004) +#define PEREN2 (0x020) +#define PERDIS2 (0x024) +#define PERCLKEN2 (0x028) +#define PERSTAT2 (0x02C) +#define PEREN3 (0x030) +#define PERDIS3 (0x034) +#define PERCLKEN3 (0x038) +#define PERSTAT3 (0x03C) +#define PEREN5 (0x050) +#define PERDIS5 (0x054) +#define PERCLKEN5 (0x058) +#define PERSTAT5 (0x05C) +#define PERRSTDIS0 (0x064) +#define PERRSTEN2 (0x078) +#define PERRSTDIS2 (0x07C) +#define PERRSTEN3 (0x084) +#define PERRSTDIS3 (0x088) +#define PERRSTSTAT3 (0x08c) +#define PERRSTEN4 (0x090) +#define PERRSTDIS4 (0x094) +#define PERRSTSTAT4 (0x098) +#define CLKDIV3 (0x0B4) +#define CLKDIV5 (0x0BC) +#define CLKDIV10 (0x0D0) +#define CLKDIV18 (0x0F0) +#define CLKDIV20 (0x0F8) +#define ISOEN (0x144) +#define ISODIS (0x148) +#define ISOSTAT (0x14c) +#define PERPWREN (0x150) +#define PERPWRDIS (0x154) +#define PERPWRSTAT (0x158) +#define PERI_AUTODIV8 (0x380) +#define PERI_AUTODIV9 (0x384) +#define PERI_AUTODIV10 (0x388) + +#define NOC_POWER_IDLEREQ (0x380) +#define NOC_POWER_IDLEACK (0x384) +#define NOC_POWER_IDLE (0x388) + +#define SCPWREN (0x0D0) +#define SCPEREN1 (0x040) +#define SCPERDIS1 (0x044) +#define SCPERCLKEN1 (0x048) +#define SCPERRSTDIS1 (0x090) +#define SCISODIS (0x0C4) +#define SCCLKDIV2 (0x258) +#define SCCLKDIV4 (0x260) + +#define PERI_CTRL23 (0x060) +#define PERI_CTRL29 (0x078) +#define PERI_CTRL30 (0x07C) +#define PERI_CTRL32 (0x084) +#define PERI_STAT0 (0x094) +#define PERI_STAT1 (0x098) +#define PERI_STAT16 (0x0D4) + +#define PCTRL_DPHYTX_ULPSEXIT1 BIT(4) +#define PCTRL_DPHYTX_ULPSEXIT0 BIT(3) + +#define PCTRL_DPHYTX_CTRL1 BIT(1) +#define PCTRL_DPHYTX_CTRL0 BIT(0) + +/******************************************************************************* + ** + */ +#define BIT_DSS_GLB_INTS BIT(30) +#define BIT_MMU_IRPT_S BIT(29) +#define BIT_MMU_IRPT_NS BIT(28) +#define BIT_DBG_MCTL_INTS BIT(27) +#define BIT_DBG_WCH1_INTS BIT(26) +#define BIT_DBG_WCH0_INTS BIT(25) +#define BIT_DBG_RCH7_INTS BIT(24) +#define BIT_DBG_RCH6_INTS BIT(23) +#define BIT_DBG_RCH5_INTS BIT(22) +#define BIT_DBG_RCH4_INTS BIT(21) +#define BIT_DBG_RCH3_INTS BIT(20) +#define BIT_DBG_RCH2_INTS BIT(19) +#define BIT_DBG_RCH1_INTS BIT(18) +#define BIT_DBG_RCH0_INTS BIT(17) +#define BIT_ITF0_INTS BIT(16) +#define BIT_DPP_INTS BIT(15) +#define BIT_CMDLIST13 BIT(14) +#define BIT_CMDLIST12 BIT(13) +#define BIT_CMDLIST11 BIT(12) +#define BIT_CMDLIST10 BIT(11) +#define BIT_CMDLIST9 BIT(10) +#define BIT_CMDLIST8 BIT(9) +#define BIT_CMDLIST7 BIT(8) +#define BIT_CMDLIST6 BIT(7) +#define BIT_CMDLIST5 BIT(6) +#define BIT_CMDLIST4 BIT(5) +#define BIT_CMDLIST3 BIT(4) +#define BIT_CMDLIST2 BIT(3) +#define BIT_CMDLIST1 BIT(2) +#define BIT_CMDLIST0 BIT(1) + +#define BIT_SDP_DSS_GLB_INTS BIT(29) +#define BIT_SDP_MMU_IRPT_S BIT(28) +#define BIT_SDP_MMU_IRPT_NS BIT(27) +#define BIT_SDP_DBG_MCTL_INTS BIT(26) +#define BIT_SDP_DBG_WCH1_INTS BIT(25) +#define BIT_SDP_DBG_WCH0_INTS BIT(24) +#define BIT_SDP_DBG_RCH7_INTS BIT(23) +#define BIT_SDP_DBG_RCH6_INTS BIT(22) +#define BIT_SDP_DBG_RCH5_INTS BIT(21) +#define BIT_SDP_DBG_RCH4_INTS BIT(20) +#define BIT_SDP_DBG_RCH3_INTS BIT(19) +#define BIT_SDP_DBG_RCH2_INTS BIT(18) +#define BIT_SDP_DBG_RCH1_INTS BIT(17) +#define BIT_SDP_DBG_RCH0_INTS BIT(16) +#define BIT_SDP_ITF1_INTS BIT(15) +#define BIT_SDP_CMDLIST13 BIT(14) +#define BIT_SDP_CMDLIST12 BIT(13) +#define BIT_SDP_CMDLIST11 BIT(12) +#define BIT_SDP_CMDLIST10 BIT(11) +#define BIT_SDP_CMDLIST9 BIT(10) +#define BIT_SDP_CMDLIST8 BIT(9) +#define BIT_SDP_CMDLIST7 BIT(8) +#define BIT_SDP_CMDLIST6 BIT(7) +#define BIT_SDP_CMDLIST5 BIT(6) +#define BIT_SDP_CMDLIST4 BIT(5) +#define BIT_SDP_CMDLIST3 BIT(4) +#define BIT_SDP_SDP_CMDLIST2 BIT(3) +#define BIT_SDP_CMDLIST1 BIT(2) +#define BIT_SDP_CMDLIST0 BIT(1) +#define BIT_SDP_RCH_CE_INTS BIT(0) + +#define BIT_OFF_DSS_GLB_INTS BIT(31) +#define BIT_OFF_MMU_IRPT_S BIT(30) +#define BIT_OFF_MMU_IRPT_NS BIT(29) +#define BIT_OFF_DBG_MCTL_INTS BIT(28) +#define BIT_OFF_DBG_WCH1_INTS BIT(27) +#define BIT_OFF_DBG_WCH0_INTS BIT(26) +#define BIT_OFF_DBG_RCH7_INTS BIT(25) +#define BIT_OFF_DBG_RCH6_INTS BIT(24) +#define BIT_OFF_DBG_RCH5_INTS BIT(23) +#define BIT_OFF_DBG_RCH4_INTS BIT(22) +#define BIT_OFF_DBG_RCH3_INTS BIT(21) +#define BIT_OFF_DBG_RCH2_INTS BIT(20) +#define BIT_OFF_DBG_RCH1_INTS BIT(19) +#define BIT_OFF_DBG_RCH0_INTS BIT(18) +#define BIT_OFF_WCH1_INTS BIT(17) +#define BIT_OFF_WCH0_INTS BIT(16) +#define BIT_OFF_WCH0_WCH1_FRM_END_INT BIT(15) +#define BIT_OFF_CMDLIST13 BIT(14) +#define BIT_OFF_CMDLIST12 BIT(13) +#define BIT_OFF_CMDLIST11 BIT(12) +#define BIT_OFF_CMDLIST10 BIT(11) +#define BIT_OFF_CMDLIST9 BIT(10) +#define BIT_OFF_CMDLIST8 BIT(9) +#define BIT_OFF_CMDLIST7 BIT(8) +#define BIT_OFF_CMDLIST6 BIT(7) +#define BIT_OFF_CMDLIST5 BIT(6) +#define BIT_OFF_CMDLIST4 BIT(5) +#define BIT_OFF_CMDLIST3 BIT(4) +#define BIT_OFF_CMDLIST2 BIT(3) +#define BIT_OFF_CMDLIST1 BIT(2) +#define BIT_OFF_CMDLIST0 BIT(1) +#define BIT_OFF_RCH_CE_INTS BIT(0) + +#define BIT_OFF_CAM_DBG_WCH2_INTS BIT(4) +#define BIT_OFF_CAM_DBG_RCH8_INTS BIT(3) +#define BIT_OFF_CAM_WCH2_FRMEND_INTS BIT(2) +#define BIT_OFF_CAM_CMDLIST15_INTS BIT(1) +#define BIT_OFF_CAM_CMDLIST14_INTS BIT(0) + +#define BIT_VACTIVE_CNT BIT(14) +#define BIT_DSI_TE_TRI BIT(13) +#define BIT_LCD_TE0_PIN BIT(12) +#define BIT_LCD_TE1_PIN BIT(11) +#define BIT_VACTIVE1_END BIT(10) +#define BIT_VACTIVE1_START BIT(9) +#define BIT_VACTIVE0_END BIT(8) +#define BIT_VACTIVE0_START BIT(7) +#define BIT_VFRONTPORCH BIT(6) +#define BIT_VBACKPORCH BIT(5) +#define BIT_VSYNC BIT(4) +#define BIT_VFRONTPORCH_END BIT(3) +#define BIT_LDI_UNFLOW BIT(2) +#define BIT_FRM_END BIT(1) +#define BIT_FRM_START BIT(0) + +#define BIT_CTL_FLUSH_EN BIT(21) +#define BIT_SCF_FLUSH_EN BIT(19) +#define BIT_DPP0_FLUSH_EN BIT(18) +#define BIT_DBUF1_FLUSH_EN BIT(17) +#define BIT_DBUF0_FLUSH_EN BIT(16) +#define BIT_OV3_FLUSH_EN BIT(15) +#define BIT_OV2_FLUSH_EN BIT(14) +#define BIT_OV1_FLUSH_EN BIT(13) +#define BIT_OV0_FLUSH_EN BIT(12) +#define BIT_WB1_FLUSH_EN BIT(11) +#define BIT_WB0_FLUSH_EN BIT(10) +#define BIT_DMA3_FLUSH_EN BIT(9) +#define BIT_DMA2_FLUSH_EN BIT(8) +#define BIT_DMA1_FLUSH_EN BIT(7) +#define BIT_DMA0_FLUSH_EN BIT(6) +#define BIT_RGB1_FLUSH_EN BIT(4) +#define BIT_RGB0_FLUSH_EN BIT(3) +#define BIT_VIG1_FLUSH_EN BIT(1) +#define BIT_VIG0_FLUSH_EN BIT(0) + +#define BIT_BUS_DBG_INT BIT(5) +#define BIT_CRC_SUM_INT BIT(4) +#define BIT_CRC_ITF1_INT BIT(3) +#define BIT_CRC_ITF0_INT BIT(2) +#define BIT_CRC_OV1_INT BIT(1) +#define BIT_CRC_OV0_INT BIT(0) + +#define BIT_SBL_SEND_FRAME_OUT BIT(19) +#define BIT_SBL_STOP_FRAME_OUT BIT(18) +#define BIT_SBL_BACKLIGHT_OUT BIT(17) +#define BIT_SBL_DARKENH_OUT BIT(16) +#define BIT_SBL_BRIGHTPTR_OUT BIT(15) +#define BIT_STRENGTH_INROI_OUT BIT(14) +#define BIT_STRENGTH_OUTROI_OUT BIT(13) +#define BIT_DONE_OUT BIT(12) +#define BIT_PPROC_DONE_OUT BIT(11) + +#define BIT_HIACE_IND BIT(8) +#define BIT_STRENGTH_INTP BIT(7) +#define BIT_BACKLIGHT_INTP BIT(6) +#define BIT_CE_END_IND BIT(5) +#define BIT_CE_CANCEL_IND BIT(4) +#define BIT_CE_LUT1_RW_COLLIDE_IND BIT(3) +#define BIT_CE_LUT0_RW_COLLIDE_IND BIT(2) +#define BIT_CE_HIST1_RW_COLLIDE_IND BIT(1) +#define BIT_CE_HIST0_RW_COLLIDE_IND BIT(0) + +/******************************************************************************* + ** MODULE BASE ADDRESS + */ + +#define DSS_MIPI_DSI0_OFFSET (0x00001000) +#define DSS_MIPI_DSI1_OFFSET (0x00001400) + +#define DSS_GLB0_OFFSET (0x12000) + +#define DSS_DBG_OFFSET (0x11000) + +#define DSS_CMDLIST_OFFSET (0x2000) + +#define DSS_SMMU_OFFSET (0x8000) + +#define DSS_VBIF0_AIF (0x7000) +#define DSS_VBIF1_AIF (0x9000) + +#define DSS_MIF_OFFSET (0xA000) + +#define DSS_MCTRL_SYS_OFFSET (0x10000) + +#define DSS_MCTRL_CTL0_OFFSET (0x10800) +#define DSS_MCTRL_CTL1_OFFSET (0x10900) +#define DSS_MCTRL_CTL2_OFFSET (0x10A00) +#define DSS_MCTRL_CTL3_OFFSET (0x10B00) +#define DSS_MCTRL_CTL4_OFFSET (0x10C00) +#define DSS_MCTRL_CTL5_OFFSET (0x10D00) + +#define DSS_RCH_VG0_DMA_OFFSET (0x20000) +#define DSS_RCH_VG0_DFC_OFFSET (0x20100) +#define DSS_RCH_VG0_SCL_OFFSET (0x20200) +#define DSS_RCH_VG0_ARSR_OFFSET (0x20300) +#define DSS_RCH_VG0_POST_CLIP_OFFSET (0x203A0) +#define DSS_RCH_VG0_PCSC_OFFSET (0x20400) +#define DSS_RCH_VG0_CSC_OFFSET (0x20500) +#define DSS_RCH_VG0_DEBUG_OFFSET (0x20600) +#define DSS_RCH_VG0_VPP_OFFSET (0x20700) +#define DSS_RCH_VG0_DMA_BUF_OFFSET (0x20800) +#define DSS_RCH_VG0_AFBCD_OFFSET (0x20900) +#define DSS_RCH_VG0_REG_DEFAULT_OFFSET (0x20A00) +#define DSS_RCH_VG0_SCL_LUT_OFFSET (0x21000) +#define DSS_RCH_VG0_ARSR_LUT_OFFSET (0x25000) + +#define DSS_RCH_VG1_DMA_OFFSET (0x28000) +#define DSS_RCH_VG1_DFC_OFFSET (0x28100) +#define DSS_RCH_VG1_SCL_OFFSET (0x28200) +#define DSS_RCH_VG1_POST_CLIP_OFFSET (0x283A0) +#define DSS_RCH_VG1_CSC_OFFSET (0x28500) +#define DSS_RCH_VG1_DEBUG_OFFSET (0x28600) +#define DSS_RCH_VG1_VPP_OFFSET (0x28700) +#define DSS_RCH_VG1_DMA_BUF_OFFSET (0x28800) +#define DSS_RCH_VG1_AFBCD_OFFSET (0x28900) +#define DSS_RCH_VG1_REG_DEFAULT_OFFSET (0x28A00) +#define DSS_RCH_VG1_SCL_LUT_OFFSET (0x29000) + +#define DSS_RCH_VG2_DMA_OFFSET (0x30000) +#define DSS_RCH_VG2_DFC_OFFSET (0x30100) +#define DSS_RCH_VG2_SCL_OFFSET (0x30200) +#define DSS_RCH_VG2_POST_CLIP_OFFSET (0x303A0) +#define DSS_RCH_VG2_CSC_OFFSET (0x30500) +#define DSS_RCH_VG2_DEBUG_OFFSET (0x30600) +#define DSS_RCH_VG2_VPP_OFFSET (0x30700) +#define DSS_RCH_VG2_DMA_BUF_OFFSET (0x30800) +#define DSS_RCH_VG2_AFBCD_OFFSET (0x30900) +#define DSS_RCH_VG2_REG_DEFAULT_OFFSET (0x30A00) +#define DSS_RCH_VG2_SCL_LUT_OFFSET (0x31000) + +#define DSS_RCH_G0_DMA_OFFSET (0x38000) +#define DSS_RCH_G0_DFC_OFFSET (0x38100) +#define DSS_RCH_G0_SCL_OFFSET (0x38200) +#define DSS_RCH_G0_POST_CLIP_OFFSET (0x383A0) +#define DSS_RCH_G0_CSC_OFFSET (0x38500) +#define DSS_RCH_G0_DEBUG_OFFSET (0x38600) +#define DSS_RCH_G0_DMA_BUF_OFFSET (0x38800) +#define DSS_RCH_G0_AFBCD_OFFSET (0x38900) +#define DSS_RCH_G0_REG_DEFAULT_OFFSET (0x38A00) + +#define DSS_RCH_G1_DMA_OFFSET (0x40000) +#define DSS_RCH_G1_DFC_OFFSET (0x40100) +#define DSS_RCH_G1_SCL_OFFSET (0x40200) +#define DSS_RCH_G1_POST_CLIP_OFFSET (0x403A0) +#define DSS_RCH_G1_CSC_OFFSET (0x40500) +#define DSS_RCH_G1_DEBUG_OFFSET (0x40600) +#define DSS_RCH_G1_DMA_BUF_OFFSET (0x40800) +#define DSS_RCH_G1_AFBCD_OFFSET (0x40900) +#define DSS_RCH_G1_REG_DEFAULT_OFFSET (0x40A00) + +#define DSS_RCH_D2_DMA_OFFSET (0x50000) +#define DSS_RCH_D2_DFC_OFFSET (0x50100) +#define DSS_RCH_D2_CSC_OFFSET (0x50500) +#define DSS_RCH_D2_DEBUG_OFFSET (0x50600) +#define DSS_RCH_D2_DMA_BUF_OFFSET (0x50800) +#define DSS_RCH_D2_AFBCD_OFFSET (0x50900) + +#define DSS_RCH_D3_DMA_OFFSET (0x51000) +#define DSS_RCH_D3_DFC_OFFSET (0x51100) +#define DSS_RCH_D3_CSC_OFFSET (0x51500) +#define DSS_RCH_D3_DEBUG_OFFSET (0x51600) +#define DSS_RCH_D3_DMA_BUF_OFFSET (0x51800) +#define DSS_RCH_D3_AFBCD_OFFSET (0x51900) + +#define DSS_RCH_D0_DMA_OFFSET (0x52000) +#define DSS_RCH_D0_DFC_OFFSET (0x52100) +#define DSS_RCH_D0_CSC_OFFSET (0x52500) +#define DSS_RCH_D0_DEBUG_OFFSET (0x52600) +#define DSS_RCH_D0_DMA_BUF_OFFSET (0x52800) +#define DSS_RCH_D0_AFBCD_OFFSET (0x52900) + +#define DSS_RCH_D1_DMA_OFFSET (0x53000) +#define DSS_RCH_D1_DFC_OFFSET (0x53100) +#define DSS_RCH_D1_CSC_OFFSET (0x53500) +#define DSS_RCH_D1_DEBUG_OFFSET (0x53600) +#define DSS_RCH_D1_DMA_BUF_OFFSET (0x53800) +#define DSS_RCH_D1_AFBCD_OFFSET (0x53900) + +#define DSS_WCH0_DMA_OFFSET (0x5A000) +#define DSS_WCH0_DFC_OFFSET (0x5A100) +#define DSS_WCH0_CSC_OFFSET (0x5A500) +#define DSS_WCH0_ROT_OFFSET (0x5A500) +#define DSS_WCH0_DEBUG_OFFSET (0x5A600) +#define DSS_WCH0_DMA_BUFFER_OFFSET (0x5A800) +#define DSS_WCH0_AFBCE_OFFSET (0x5A900) + +#define DSS_WCH1_DMA_OFFSET (0x5C000) +#define DSS_WCH1_DFC_OFFSET (0x5C100) +#define DSS_WCH1_CSC_OFFSET (0x5C500) +#define DSS_WCH1_ROT_OFFSET (0x5C500) +#define DSS_WCH1_DEBUG_OFFSET (0x5C600) +#define DSS_WCH1_DMA_BUFFER_OFFSET (0x5C800) +#define DSS_WCH1_AFBCE_OFFSET (0x5C900) + +#define DSS_WCH2_DMA_OFFSET (0x5E000) +#define DSS_WCH2_DFC_OFFSET (0x5E100) +#define DSS_WCH2_CSC_OFFSET (0x5E500) +#define DSS_WCH2_ROT_OFFSET (0x5E500) +#define DSS_WCH2_DEBUG_OFFSET (0x5E600) +#define DSS_WCH2_DMA_BUFFER_OFFSET (0x5E800) +#define DSS_WCH2_AFBCE_OFFSET (0x5E900) + +#define DSS_OVL0_OFFSET (0x60000) +#define DSS_OVL1_OFFSET (0x60400) +#define DSS_OVL2_OFFSET (0x60800) +#define DSS_OVL3_OFFSET (0x60C00) + +#define DSS_DBUF0_OFFSET (0x6D000) +#define DSS_DBUF1_OFFSET (0x6E000) + +#define DSS_HI_ACE_OFFSET (0x6F000) + +#define DSS_DPP_OFFSET (0x70000) +#define DSS_TOP_OFFSET (0x70000) +#define DSS_DPP_COLORBAR_OFFSET (0x70100) +#define DSS_DPP_DITHER_OFFSET (0x70200) +#define DSS_DPP_CSC_RGB2YUV10B_OFFSET (0x70300) +#define DSS_DPP_CSC_YUV2RGB10B_OFFSET (0x70400) +#define DSS_DPP_DEGAMA_OFFSET (0x70500) +#define DSS_DPP_GAMA_OFFSET (0x70600) +#define DSS_DPP_ACM_OFFSET (0x70700) +#define DSS_DPP_ACE_OFFSET (0x70800) +#define DSS_DPP_LCP_OFFSET (0x70900) +#define DSS_DPP_ARSR1P_OFFSET (0x70A00) +#define DSS_DPP_BITEXT0_OFFSET (0x70B00) +#define DSS_DPP_GAMA_LUT_OFFSET (0x71000) +#define DSS_DPP_ACM_LUT_OFFSET (0x72000) +#define DSS_DPP_LCP_LUT_OFFSET (0x73000) +#define DSS_DPP_ACE_LUT_OFFSET (0x79000) +#define DSS_DPP_ARSR1P_LUT_OFFSET (0x7B000) + +#define DSS_POST_SCF_OFFSET DSS_DPP_ARSR1P_OFFSET +#define DSS_POST_SCF_LUT_OFFSET DSS_DPP_ARSR1P_LUT_OFFSET + +#define DSS_DPP_SBL_OFFSET (0x7C000) +#define DSS_LDI0_OFFSET (0x7D000) +#define DSS_IFBC_OFFSET (0x7D800) +#define DSS_DSC_OFFSET (0x7DC00) +#define DSS_LDI1_OFFSET (0x7E000) + +/******************************************************************************* + ** GLB + */ +#define GLB_DSS_TAG (DSS_GLB0_OFFSET + 0x0000) + +#define GLB_APB_CTL (DSS_GLB0_OFFSET + 0x0004) + +#define GLB_DSS_AXI_RST_EN (DSS_GLB0_OFFSET + 0x0118) +#define GLB_DSS_APB_RST_EN (DSS_GLB0_OFFSET + 0x011C) +#define GLB_DSS_CORE_RST_EN (DSS_GLB0_OFFSET + 0x0120) +#define GLB_PXL0_DIV2_RST_EN (DSS_GLB0_OFFSET + 0x0124) +#define GLB_PXL0_DIV4_RST_EN (DSS_GLB0_OFFSET + 0x0128) +#define GLB_PXL0_RST_EN (DSS_GLB0_OFFSET + 0x012C) +#define GLB_PXL0_DSI_RST_EN (DSS_GLB0_OFFSET + 0x0130) +#define GLB_DSS_PXL1_RST_EN (DSS_GLB0_OFFSET + 0x0134) +#define GLB_MM_AXI_CLK_RST_EN (DSS_GLB0_OFFSET + 0x0138) +#define GLB_AFBCD0_IP_RST_EN (DSS_GLB0_OFFSET + 0x0140) +#define GLB_AFBCD1_IP_RST_EN (DSS_GLB0_OFFSET + 0x0144) +#define GLB_AFBCD2_IP_RST_EN (DSS_GLB0_OFFSET + 0x0148) +#define GLB_AFBCD3_IP_RST_EN (DSS_GLB0_OFFSET + 0x014C) +#define GLB_AFBCD4_IP_RST_EN (DSS_GLB0_OFFSET + 0x0150) +#define GLB_AFBCD5_IP_RST_EN (DSS_GLB0_OFFSET + 0x0154) +#define GLB_AFBCD6_IP_RST_EN (DSS_GLB0_OFFSET + 0x0158) +#define GLB_AFBCD7_IP_RST_EN (DSS_GLB0_OFFSET + 0x015C) +#define GLB_AFBCE0_IP_RST_EN (DSS_GLB0_OFFSET + 0x0160) +#define GLB_AFBCE1_IP_RST_EN (DSS_GLB0_OFFSET + 0x0164) + +#define GLB_MCU_PDP_INTS (DSS_GLB0_OFFSET + 0x20C) +#define GLB_MCU_PDP_INT_MSK (DSS_GLB0_OFFSET + 0x210) +#define GLB_MCU_SDP_INTS (DSS_GLB0_OFFSET + 0x214) +#define GLB_MCU_SDP_INT_MSK (DSS_GLB0_OFFSET + 0x218) +#define GLB_MCU_OFF_INTS (DSS_GLB0_OFFSET + 0x21C) +#define GLB_MCU_OFF_INT_MSK (DSS_GLB0_OFFSET + 0x220) +#define GLB_MCU_OFF_CAM_INTS (DSS_GLB0_OFFSET + 0x2B4) +#define GLB_MCU_OFF_CAM_INT_MSK (DSS_GLB0_OFFSET + 0x2B8) +#define GLB_CPU_PDP_INTS (DSS_GLB0_OFFSET + 0x224) +#define GLB_CPU_PDP_INT_MSK (DSS_GLB0_OFFSET + 0x228) +#define GLB_CPU_SDP_INTS (DSS_GLB0_OFFSET + 0x22C) +#define GLB_CPU_SDP_INT_MSK (DSS_GLB0_OFFSET + 0x230) +#define GLB_CPU_OFF_INTS (DSS_GLB0_OFFSET + 0x234) +#define GLB_CPU_OFF_INT_MSK (DSS_GLB0_OFFSET + 0x238) +#define GLB_CPU_OFF_CAM_INTS (DSS_GLB0_OFFSET + 0x2AC) +#define GLB_CPU_OFF_CAM_INT_MSK (DSS_GLB0_OFFSET + 0x2B0) + +#define GLB_MODULE_CLK_SEL (DSS_GLB0_OFFSET + 0x0300) +#define GLB_MODULE_CLK_EN (DSS_GLB0_OFFSET + 0x0304) + +#define GLB_GLB0_DBG_SEL (DSS_GLB0_OFFSET + 0x310) +#define GLB_GLB1_DBG_SEL (DSS_GLB0_OFFSET + 0x314) +#define GLB_DBG_IRQ_CPU (DSS_GLB0_OFFSET + 0x320) +#define GLB_DBG_IRQ_MCU (DSS_GLB0_OFFSET + 0x324) + +#define GLB_TP_SEL (DSS_GLB0_OFFSET + 0x0400) +#define GLB_CRC_DBG_LDI0 (DSS_GLB0_OFFSET + 0x0404) +#define GLB_CRC_DBG_LDI1 (DSS_GLB0_OFFSET + 0x0408) +#define GLB_CRC_LDI0_EN (DSS_GLB0_OFFSET + 0x040C) +#define GLB_CRC_LDI0_FRM (DSS_GLB0_OFFSET + 0x0410) +#define GLB_CRC_LDI1_EN (DSS_GLB0_OFFSET + 0x0414) +#define GLB_CRC_LDI1_FRM (DSS_GLB0_OFFSET + 0x0418) + +#define GLB_DSS_MEM_CTRL (DSS_GLB0_OFFSET + 0x0600) +#define GLB_DSS_PM_CTRL (DSS_GLB0_OFFSET + 0x0604) + +/******************************************************************************* + ** DBG + */ +#define DBG_CRC_DBG_OV0 (0x0000) +#define DBG_CRC_DBG_OV1 (0x0004) +#define DBG_CRC_DBG_SUM (0x0008) +#define DBG_CRC_OV0_EN (0x000C) +#define DBG_DSS_GLB_DBG_O (0x0010) +#define DBG_DSS_GLB_DBG_I (0x0014) +#define DBG_CRC_OV0_FRM (0x0018) +#define DBG_CRC_OV1_EN (0x001C) +#define DBG_CRC_OV1_FRM (0x0020) +#define DBG_CRC_SUM_EN (0x0024) +#define DBG_CRC_SUM_FRM (0x0028) + +#define DBG_MCTL_INTS (0x023C) +#define DBG_MCTL_INT_MSK (0x0240) +#define DBG_WCH0_INTS (0x0244) +#define DBG_WCH0_INT_MSK (0x0248) +#define DBG_WCH1_INTS (0x024C) +#define DBG_WCH1_INT_MSK (0x0250) +#define DBG_RCH0_INTS (0x0254) +#define DBG_RCH0_INT_MSK (0x0258) +#define DBG_RCH1_INTS (0x025C) +#define DBG_RCH1_INT_MSK (0x0260) +#define DBG_RCH2_INTS (0x0264) +#define DBG_RCH2_INT_MSK (0x0268) +#define DBG_RCH3_INTS (0x026C) +#define DBG_RCH3_INT_MSK (0x0270) +#define DBG_RCH4_INTS (0x0274) +#define DBG_RCH4_INT_MSK (0x0278) +#define DBG_RCH5_INTS (0x027C) +#define DBG_RCH5_INT_MSK (0x0280) +#define DBG_RCH6_INTS (0x0284) +#define DBG_RCH6_INT_MSK (0x0288) +#define DBG_RCH7_INTS (0x028C) +#define DBG_RCH7_INT_MSK (0x0290) +#define DBG_DSS_GLB_INTS (0x0294) +#define DBG_DSS_GLB_INT_MSK (0x0298) +#define DBG_WCH2_INTS (0x029C) +#define DBG_WCH2_INT_MSK (0x02A0) +#define DBG_RCH8_INTS (0x02A4) +#define DBG_RCH8_INT_MSK (0x02A8) + +/******************************************************************************* + ** CMDLIST + */ + +#define CMDLIST_CH0_PENDING_CLR (0x0000) +#define CMDLIST_CH0_CTRL (0x0004) +#define CMDLIST_CH0_STATUS (0x0008) +#define CMDLIST_CH0_STAAD (0x000C) +#define CMDLIST_CH0_CURAD (0x0010) +#define CMDLIST_CH0_INTE (0x0014) +#define CMDLIST_CH0_INTC (0x0018) +#define CMDLIST_CH0_INTS (0x001C) +#define CMDLIST_CH0_SCENE (0x0020) +#define CMDLIST_CH0_DBG (0x0028) + +#define CMDLIST_DBG (0x0700) +#define CMDLIST_BUF_DBG_EN (0x0704) +#define CMDLIST_BUF_DBG_CNT_CLR (0x0708) +#define CMDLIST_BUF_DBG_CNT (0x070C) +#define CMDLIST_TIMEOUT_TH (0x0710) +#define CMDLIST_START (0x0714) +#define CMDLIST_ADDR_MASK_EN (0x0718) +#define CMDLIST_ADDR_MASK_DIS (0x071C) +#define CMDLIST_ADDR_MASK_STATUS (0x0720) +#define CMDLIST_TASK_CONTINUE (0x0724) +#define CMDLIST_TASK_STATUS (0x0728) +#define CMDLIST_CTRL (0x072C) +#define CMDLIST_SECU (0x0730) +#define CMDLIST_INTS (0x0734) +#define CMDLIST_SWRST (0x0738) +#define CMD_MEM_CTRL (0x073C) +#define CMD_CLK_SEL (0x0740) +#define CMD_CLK_EN (0x0744) + +#define HISI_DSS_MIN_ROT_AFBCE_BLOCK_SIZE (256) +#define HISI_DSS_MAX_ROT_AFBCE_BLOCK_SIZE (480) + +#define BIT_CMDLIST_CH_TASKDONE_INTS BIT(7) +#define BIT_CMDLIST_CH_TIMEOUT_INTS BIT(6) +#define BIT_CMDLIST_CH_BADCMD_INTS BIT(5) +#define BIT_CMDLIST_CH_START_INTS BIT(4) +#define BIT_CMDLIST_CH_PENDING_INTS BIT(3) +#define BIT_CMDLIST_CH_AXIERR_INTS BIT(2) +#define BIT_CMDLIST_CH_ALLDONE_INTS BIT(1) +#define BIT_CMDLIST_CH_ONEDONE_INTS BIT(0) + +#define BIT_CMDLIST_CH15_INTS BIT(15) +#define BIT_CMDLIST_CH14_INTS BIT(14) +#define BIT_CMDLIST_CH13_INTS BIT(13) +#define BIT_CMDLIST_CH12_INTS BIT(12) +#define BIT_CMDLIST_CH11_INTS BIT(11) +#define BIT_CMDLIST_CH10_INTS BIT(10) +#define BIT_CMDLIST_CH9_INTS BIT(9) +#define BIT_CMDLIST_CH8_INTS BIT(8) +#define BIT_CMDLIST_CH7_INTS BIT(7) +#define BIT_CMDLIST_CH6_INTS BIT(6) +#define BIT_CMDLIST_CH5_INTS BIT(5) +#define BIT_CMDLIST_CH4_INTS BIT(4) +#define BIT_CMDLIST_CH3_INTS BIT(3) +#define BIT_CMDLIST_CH2_INTS BIT(2) +#define BIT_CMDLIST_CH1_INTS BIT(1) +#define BIT_CMDLIST_CH0_INTS BIT(0) + +/******************************************************************************* + ** AIF + */ +#define AIF0_CH0_OFFSET (DSS_VBIF0_AIF + 0x00) +#define AIF0_CH0_ADD_OFFSET (DSS_VBIF0_AIF + 0x04) +#define AIF0_CH1_OFFSET (DSS_VBIF0_AIF + 0x20) +#define AIF0_CH1_ADD_OFFSET (DSS_VBIF0_AIF + 0x24) +#define AIF0_CH2_OFFSET (DSS_VBIF0_AIF + 0x40) +#define AIF0_CH2_ADD_OFFSET (DSS_VBIF0_AIF + 0x44) +#define AIF0_CH3_OFFSET (DSS_VBIF0_AIF + 0x60) +#define AIF0_CH3_ADD_OFFSET (DSS_VBIF0_AIF + 0x64) +#define AIF0_CH4_OFFSET (DSS_VBIF0_AIF + 0x80) +#define AIF0_CH4_ADD_OFFSET (DSS_VBIF0_AIF + 0x84) +#define AIF0_CH5_OFFSET (DSS_VBIF0_AIF + 0xA0) +#define AIF0_CH5_ADD_OFFSET (DSS_VBIF0_AIF + 0xa4) +#define AIF0_CH6_OFFSET (DSS_VBIF0_AIF + 0xC0) +#define AIF0_CH6_ADD_OFFSET (DSS_VBIF0_AIF + 0xc4) +#define AIF0_CH7_OFFSET (DSS_VBIF0_AIF + 0xE0) +#define AIF0_CH7_ADD_OFFSET (DSS_VBIF0_AIF + 0xe4) +#define AIF0_CH8_OFFSET (DSS_VBIF0_AIF + 0x100) +#define AIF0_CH8_ADD_OFFSET (DSS_VBIF0_AIF + 0x104) +#define AIF0_CH9_OFFSET (DSS_VBIF0_AIF + 0x120) +#define AIF0_CH9_ADD_OFFSET (DSS_VBIF0_AIF + 0x124) +#define AIF0_CH10_OFFSET (DSS_VBIF0_AIF + 0x140) +#define AIF0_CH10_ADD_OFFSET (DSS_VBIF0_AIF + 0x144) +#define AIF0_CH11_OFFSET (DSS_VBIF0_AIF + 0x160) +#define AIF0_CH11_ADD_OFFSET (DSS_VBIF0_AIF + 0x164) +#define AIF0_CH12_OFFSET (DSS_VBIF0_AIF + 0x180) +#define AIF0_CH12_ADD_OFFSET (DSS_VBIF0_AIF + 0x184) + +#define AIF1_CH0_OFFSET (DSS_VBIF1_AIF + 0x00) +#define AIF1_CH0_ADD_OFFSET (DSS_VBIF1_AIF + 0x04) +#define AIF1_CH1_OFFSET (DSS_VBIF1_AIF + 0x20) +#define AIF1_CH1_ADD_OFFSET (DSS_VBIF1_AIF + 0x24) +#define AIF1_CH2_OFFSET (DSS_VBIF1_AIF + 0x40) +#define AIF1_CH2_ADD_OFFSET (DSS_VBIF1_AIF + 0x44) +#define AIF1_CH3_OFFSET (DSS_VBIF1_AIF + 0x60) +#define AIF1_CH3_ADD_OFFSET (DSS_VBIF1_AIF + 0x64) +#define AIF1_CH4_OFFSET (DSS_VBIF1_AIF + 0x80) +#define AIF1_CH4_ADD_OFFSET (DSS_VBIF1_AIF + 0x84) +#define AIF1_CH5_OFFSET (DSS_VBIF1_AIF + 0xA0) +#define AIF1_CH5_ADD_OFFSET (DSS_VBIF1_AIF + 0xa4) +#define AIF1_CH6_OFFSET (DSS_VBIF1_AIF + 0xC0) +#define AIF1_CH6_ADD_OFFSET (DSS_VBIF1_AIF + 0xc4) +#define AIF1_CH7_OFFSET (DSS_VBIF1_AIF + 0xE0) +#define AIF1_CH7_ADD_OFFSET (DSS_VBIF1_AIF + 0xe4) +#define AIF1_CH8_OFFSET (DSS_VBIF1_AIF + 0x100) +#define AIF1_CH8_ADD_OFFSET (DSS_VBIF1_AIF + 0x104) +#define AIF1_CH9_OFFSET (DSS_VBIF1_AIF + 0x120) +#define AIF1_CH9_ADD_OFFSET (DSS_VBIF1_AIF + 0x124) +#define AIF1_CH10_OFFSET (DSS_VBIF1_AIF + 0x140) +#define AIF1_CH10_ADD_OFFSET (DSS_VBIF1_AIF + 0x144) +#define AIF1_CH11_OFFSET (DSS_VBIF1_AIF + 0x160) +#define AIF1_CH11_ADD_OFFSET (DSS_VBIF1_AIF + 0x164) +#define AIF1_CH12_OFFSET (DSS_VBIF1_AIF + 0x180) +#define AIF1_CH12_ADD_OFFSET (DSS_VBIF1_AIF + 0x184) + +/* aif dmax */ + +#define AIF_CH_CTL (0x0000) + +#define AIF_CH_CTL_ADD (0x0004) + +/* aif common */ +#define AXI0_RID_MSK0 (0x0800) +#define AXI0_RID_MSK1 (0x0804) +#define AXI0_WID_MSK (0x0808) +#define AXI0_R_QOS_MAP (0x080c) +#define AXI1_RID_MSK0 (0x0810) +#define AXI1_RID_MSK1 (0x0814) +#define AXI1_WID_MSK (0x0818) +#define AXI1_R_QOS_MAP (0x081c) +#define AIF_CLK_SEL0 (0x0820) +#define AIF_CLK_SEL1 (0x0824) +#define AIF_CLK_EN0 (0x0828) +#define AIF_CLK_EN1 (0x082c) +#define MONITOR_CTRL (0x0830) +#define MONITOR_TIMER_INI (0x0834) +#define DEBUG_BUF_BASE (0x0838) +#define DEBUG_CTRL (0x083C) +#define AIF_SHADOW_READ (0x0840) +#define AIF_MEM_CTRL (0x0844) +#define AIF_MONITOR_EN (0x0848) +#define AIF_MONITOR_CTRL (0x084C) +#define AIF_MONITOR_SAMPLE_MUN (0x0850) +#define AIF_MONITOR_SAMPLE_TIME (0x0854) +#define AIF_MONITOR_SAMPLE_FLOW (0x0858) + +/* aif debug */ +#define AIF_MONITOR_READ_DATA (0x0880) +#define AIF_MONITOR_WRITE_DATA (0x0884) +#define AIF_MONITOR_WINDOW_CYCLE (0x0888) +#define AIF_MONITOR_WBURST_CNT (0x088C) +#define AIF_MONITOR_MIN_WR_CYCLE (0x0890) +#define AIF_MONITOR_MAX_WR_CYCLE (0x0894) +#define AIF_MONITOR_AVR_WR_CYCLE (0x0898) +#define AIF_MONITOR_MIN_WRW_CYCLE (0x089C) +#define AIF_MONITOR_MAX_WRW_CYCLE (0x08A0) +#define AIF_MONITOR_AVR_WRW_CYCLE (0x08A4) +#define AIF_MONITOR_RBURST_CNT (0x08A8) +#define AIF_MONITOR_MIN_RD_CYCLE (0x08AC) +#define AIF_MONITOR_MAX_RD_CYCLE (0x08B0) +#define AIF_MONITOR_AVR_RD_CYCLE (0x08B4) +#define AIF_MONITOR_MIN_RDW_CYCLE (0x08B8) +#define AIF_MONITOR_MAX_RDW_CYCLE (0x08BC) +#define AIF_MONITOR_AVR_RDW_CYCLE (0x08C0) +#define AIF_CH_STAT_0 (0x08C4) +#define AIF_CH_STAT_1 (0x08C8) + +#define AIF_MODULE_CLK_SEL (0x0A04) +#define AIF_MODULE_CLK_EN (0x0A08) + +typedef struct dss_aif { + u32 aif_ch_ctl; + u32 aif_ch_ctl_add; +} dss_aif_t; + +typedef struct dss_aif_bw { + u64 bw; + u8 chn_idx; + s8 axi_sel; + u8 is_used; +} dss_aif_bw_t; + +/******************************************************************************* + ** MIF + */ +#define MIF_ENABLE (0x0000) +#define MIF_MEM_CTRL (0x0004) + +#define MIF_CTRL0 (0x000) +#define MIF_CTRL1 (0x004) +#define MIF_CTRL2 (0x008) +#define MIF_CTRL3 (0x00C) +#define MIF_CTRL4 (0x010) +#define MIF_CTRL5 (0x014) +#define REG_DEFAULT (0x0500) +#define MIF_SHADOW_READ (0x0504) +#define MIF_CLK_CTL (0x0508) + +#define MIF_STAT0 (0x0600) + +#define MIF_STAT1 (0x0604) + +#define MIF_STAT2 (0x0608) + +#define MIF_CTRL_OFFSET (0x20) +#define MIF_CH0_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 1) +#define MIF_CH1_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 2) +#define MIF_CH2_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 3) +#define MIF_CH3_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 4) +#define MIF_CH4_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 5) +#define MIF_CH5_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 6) +#define MIF_CH6_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 7) +#define MIF_CH7_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 8) +#define MIF_CH8_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 9) +#define MIF_CH9_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 10) +#define MIF_CH10_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 11) +#define MIF_CH11_OFFSET (DSS_MIF_OFFSET + MIF_CTRL_OFFSET * 12) +#define MIF_CTRL_NUM (12) + +#define LITTLE_LAYER_BUF_SIZE (256 * 1024) +#define MIF_STRIDE_UNIT (4 * 1024) + +typedef struct dss_mif { + u32 mif_ctrl1; + u32 mif_ctrl2; + u32 mif_ctrl3; + u32 mif_ctrl4; + u32 mif_ctrl5; +} dss_mif_t; + +/* + ** stretch blt, linear/tile, rotation, pixel format + ** 0 0 000 + */ +enum dss_mmu_tlb_tag_org { + MMU_TLB_TAG_ORG_0x0 = 0x0, + MMU_TLB_TAG_ORG_0x1 = 0x1, + MMU_TLB_TAG_ORG_0x2 = 0x2, + MMU_TLB_TAG_ORG_0x3 = 0x3, + MMU_TLB_TAG_ORG_0x4 = 0x4, + MMU_TLB_TAG_ORG_0x7 = 0x7, + + MMU_TLB_TAG_ORG_0x8 = 0x8, + MMU_TLB_TAG_ORG_0x9 = 0x9, + MMU_TLB_TAG_ORG_0xA = 0xA, + MMU_TLB_TAG_ORG_0xB = 0xB, + MMU_TLB_TAG_ORG_0xC = 0xC, + MMU_TLB_TAG_ORG_0xF = 0xF, + + MMU_TLB_TAG_ORG_0x10 = 0x10, + MMU_TLB_TAG_ORG_0x11 = 0x11, + MMU_TLB_TAG_ORG_0x12 = 0x12, + MMU_TLB_TAG_ORG_0x13 = 0x13, + MMU_TLB_TAG_ORG_0x14 = 0x14, + MMU_TLB_TAG_ORG_0x17 = 0x17, + + MMU_TLB_TAG_ORG_0x18 = 0x18, + MMU_TLB_TAG_ORG_0x19 = 0x19, + MMU_TLB_TAG_ORG_0x1A = 0x1A, + MMU_TLB_TAG_ORG_0x1B = 0x1B, + MMU_TLB_TAG_ORG_0x1C = 0x1C, + MMU_TLB_TAG_ORG_0x1F = 0x1F, +}; + +/******************************************************************************* + **SMMU + */ +#define SMMU_SCR (0x0000) +#define SMMU_MEMCTRL (0x0004) +#define SMMU_LP_CTRL (0x0008) +#define SMMU_PRESS_REMAP (0x000C) +#define SMMU_INTMASK_NS (0x0010) +#define SMMU_INTRAW_NS (0x0014) +#define SMMU_INTSTAT_NS (0x0018) +#define SMMU_INTCLR_NS (0x001C) + +#define SMMU_SMRx_NS (0x0020) +#define SMMU_RLD_EN0_NS (0x01F0) +#define SMMU_RLD_EN1_NS (0x01F4) +#define SMMU_RLD_EN2_NS (0x01F8) +#define SMMU_CB_SCTRL (0x0200) +#define SMMU_CB_TTBR0 (0x0204) +#define SMMU_CB_TTBR1 (0x0208) +#define SMMU_CB_TTBCR (0x020C) +#define SMMU_OFFSET_ADDR_NS (0x0210) +#define SMMU_SCACHEI_ALL (0x0214) +#define SMMU_SCACHEI_L1 (0x0218) +#define SMMU_SCACHEI_L2L3 (0x021C) +#define SMMU_FAMA_CTRL0 (0x0220) +#define SMMU_FAMA_CTRL1 (0x0224) +#define SMMU_ADDR_MSB (0x0300) +#define SMMU_ERR_RDADDR (0x0304) +#define SMMU_ERR_WRADDR (0x0308) +#define SMMU_FAULT_ADDR_TCU (0x0310) +#define SMMU_FAULT_ID_TCU (0x0314) + +#define SMMU_FAULT_ADDR_TBUx (0x0320) +#define SMMU_FAULT_ID_TBUx (0x0324) +#define SMMU_FAULT_INFOx (0x0328) +#define SMMU_DBGRPTR_TLB (0x0380) +#define SMMU_DBGRDATA_TLB (0x0380) +#define SMMU_DBGRDATA0_CACHE (0x038C) +#define SMMU_DBGRDATA1_CACHE (0x0390) +#define SMMU_DBGAXI_CTRL (0x0394) +#define SMMU_OVA_ADDR (0x0398) +#define SMMU_OPA_ADDR (0x039C) +#define SMMU_OVA_CTRL (0x03A0) +#define SMMU_OPREF_ADDR (0x03A4) +#define SMMU_OPREF_CTRL (0x03A8) +#define SMMU_OPREF_CNT (0x03AC) + +#define SMMU_SMRx_S (0x0500) +#define SMMU_RLD_EN0_S (0x06F0) +#define SMMU_RLD_EN1_S (0x06F4) +#define SMMU_RLD_EN2_S (0x06F8) +#define SMMU_INTMAS_S (0x0700) +#define SMMU_INTRAW_S (0x0704) +#define SMMU_INTSTAT_S (0x0708) +#define SMMU_INTCLR_S (0x070C) +#define SMMU_SCR_S (0x0710) +#define SMMU_SCB_SCTRL (0x0714) +#define SMMU_SCB_TTBR (0x0718) +#define SMMU_SCB_TTBCR (0x071C) +#define SMMU_OFFSET_ADDR_S (0x0720) + +#define SMMU_SID_NUM (64) + +typedef struct dss_smmu { + u32 smmu_scr; + u32 smmu_memctrl; + u32 smmu_lp_ctrl; + u32 smmu_press_remap; + u32 smmu_intmask_ns; + u32 smmu_intraw_ns; + u32 smmu_intstat_ns; + u32 smmu_intclr_ns; + u32 smmu_smrx_ns[SMMU_SID_NUM]; + u32 smmu_rld_en0_ns; + u32 smmu_rld_en1_ns; + u32 smmu_rld_en2_ns; + u32 smmu_cb_sctrl; + u32 smmu_cb_ttbr0; + u32 smmu_cb_ttbr1; + u32 smmu_cb_ttbcr; + u32 smmu_offset_addr_ns; + u32 smmu_scachei_all; + u32 smmu_scachei_l1; + u32 smmu_scachei_l2l3; + u32 smmu_fama_ctrl0_ns; + u32 smmu_fama_ctrl1_ns; + u32 smmu_addr_msb; + u32 smmu_err_rdaddr; + u32 smmu_err_wraddr; + u32 smmu_fault_addr_tcu; + u32 smmu_fault_id_tcu; + u32 smmu_fault_addr_tbux; + u32 smmu_fault_id_tbux; + u32 smmu_fault_infox; + u32 smmu_dbgrptr_tlb; + u32 smmu_dbgrdata_tlb; + u32 smmu_dbgrptr_cache; + u32 smmu_dbgrdata0_cache; + u32 smmu_dbgrdata1_cache; + u32 smmu_dbgaxi_ctrl; + u32 smmu_ova_addr; + u32 smmu_opa_addr; + u32 smmu_ova_ctrl; + u32 smmu_opref_addr; + u32 smmu_opref_ctrl; + u32 smmu_opref_cnt; + u32 smmu_smrx_s[SMMU_SID_NUM]; + u32 smmu_rld_en0_s; + u32 smmu_rld_en1_s; + u32 smmu_rld_en2_s; + u32 smmu_intmas_s; + u32 smmu_intraw_s; + u32 smmu_intstat_s; + u32 smmu_intclr_s; + u32 smmu_scr_s; + u32 smmu_scb_sctrl; + u32 smmu_scb_ttbr; + u32 smmu_scb_ttbcr; + u32 smmu_offset_addr_s; + + u8 smmu_smrx_ns_used[DSS_CHN_MAX_DEFINE]; +} dss_smmu_t; + +/******************************************************************************* + ** RDMA + */ + +#define DMA_OFT_X0 (0x0000) +#define DMA_OFT_Y0 (0x0004) +#define DMA_OFT_X1 (0x0008) +#define DMA_OFT_Y1 (0x000C) +#define DMA_MASK0 (0x0010) +#define DMA_MASK1 (0x0014) +#define DMA_STRETCH_SIZE_VRT (0x0018) +#define DMA_CTRL (0x001C) +#define DMA_TILE_SCRAM (0x0020) + +#define DMA_PULSE (0x0028) +#define DMA_CORE_GT (0x002C) +#define RWCH_CFG0 (0x0030) + +#define WDMA_DMA_SW_MASK_EN (0x004C) +#define WDMA_DMA_START_MASK0 (0x0050) +#define WDMA_DMA_END_MASK0 (0x0054) +#define WDMA_DMA_START_MASK1 (0x0058) +#define WDMA_DMA_END_MASK1 (0x005C) + +#define DMA_DATA_ADDR0 (0x0060) +#define DMA_STRIDE0 (0x0064) +#define DMA_STRETCH_STRIDE0 (0x0068) +#define DMA_DATA_NUM0 (0x006C) + +#define DMA_TEST0 (0x0070) +#define DMA_TEST1 (0x0074) +#define DMA_TEST3 (0x0078) +#define DMA_TEST4 (0x007C) +#define DMA_STATUS_Y (0x0080) + +#define DMA_DATA_ADDR1 (0x0084) +#define DMA_STRIDE1 (0x0088) +#define DMA_STRETCH_STRIDE1 (0x008C) +#define DMA_DATA_NUM1 (0x0090) + +#define DMA_TEST0_U (0x0094) +#define DMA_TEST1_U (0x0098) +#define DMA_TEST3_U (0x009C) +#define DMA_TEST4_U (0x00A0) +#define DMA_STATUS_U (0x00A4) + +#define DMA_DATA_ADDR2 (0x00A8) +#define DMA_STRIDE2 (0x00AC) +#define DMA_STRETCH_STRIDE2 (0x00B0) +#define DMA_DATA_NUM2 (0x00B4) + +#define DMA_TEST0_V (0x00B8) +#define DMA_TEST1_V (0x00BC) +#define DMA_TEST3_V (0x00C0) +#define DMA_TEST4_V (0x00C4) +#define DMA_STATUS_V (0x00C8) + +#define CH_RD_SHADOW (0x00D0) +#define CH_CTL (0x00D4) +#define CH_SECU_EN (0x00D8) +#define CH_SW_END_REQ (0x00DC) +#define CH_CLK_SEL (0x00E0) +#define CH_CLK_EN (0x00E4) + +/******************************************************************************* + ** DFC + */ +#define DFC_DISP_SIZE (0x0000) +#define DFC_PIX_IN_NUM (0x0004) +#define DFC_GLB_ALPHA (0x0008) +#define DFC_DISP_FMT (0x000C) +#define DFC_CLIP_CTL_HRZ (0x0010) +#define DFC_CLIP_CTL_VRZ (0x0014) +#define DFC_CTL_CLIP_EN (0x0018) +#define DFC_ICG_MODULE (0x001C) +#define DFC_DITHER_ENABLE (0x0020) +#define DFC_PADDING_CTL (0x0024) + +typedef struct dss_dfc { + u32 disp_size; + u32 pix_in_num; + u32 disp_fmt; + u32 clip_ctl_hrz; + u32 clip_ctl_vrz; + u32 ctl_clip_en; + u32 icg_module; + u32 dither_enable; + u32 padding_ctl; +} dss_dfc_t; + +/******************************************************************************* + ** SCF + */ +#define DSS_SCF_H0_Y_COEF_OFFSET (0x0000) +#define DSS_SCF_Y_COEF_OFFSET (0x2000) +#define DSS_SCF_UV_COEF_OFFSET (0x2800) + +#define SCF_EN_HSCL_STR (0x0000) +#define SCF_EN_VSCL_STR (0x0004) +#define SCF_H_V_ORDER (0x0008) +#define SCF_SCF_CORE_GT (0x000C) +#define SCF_INPUT_WIDTH_HEIGHT (0x0010) +#define SCF_OUTPUT_WIDTH_HEIGHT (0x0014) +#define SCF_COEF_MEM_CTRL (0x0018) +#define SCF_EN_HSCL (0x001C) +#define SCF_EN_VSCL (0x0020) +#define SCF_ACC_HSCL (0x0024) +#define SCF_ACC_HSCL1 (0x0028) +#define SCF_INC_HSCL (0x0034) +#define SCF_ACC_VSCL (0x0038) +#define SCF_ACC_VSCL1 (0x003C) +#define SCF_INC_VSCL (0x0048) +#define SCF_EN_NONLINEAR (0x004C) +#define SCF_EN_MMP (0x007C) +#define SCF_DB_H0 (0x0080) +#define SCF_DB_H1 (0x0084) +#define SCF_DB_V0 (0x0088) +#define SCF_DB_V1 (0x008C) +#define SCF_LB_MEM_CTRL (0x0090) +#define SCF_RD_SHADOW (0x00F0) +#define SCF_CLK_SEL (0x00F8) +#define SCF_CLK_EN (0x00FC) + +/* MACROS */ +#define SCF_MIN_INPUT (16) +#define SCF_MIN_OUTPUT (16) + +/* Threshold for SCF Stretch and SCF filter */ +#define RDMA_STRETCH_THRESHOLD (2) +#define SCF_INC_FACTOR (1 << 18) +#define SCF_UPSCALE_MAX (60) +#define SCF_DOWNSCALE_MAX (60) +#define SCF_EDGE_FACTOR (3) +#define ARSR2P_INC_FACTOR (65536) + +typedef struct dss_scl { + u32 en_hscl_str; + u32 en_vscl_str; + u32 h_v_order; + u32 input_width_height; + u32 output_width_height; + u32 en_hscl; + u32 en_vscl; + u32 acc_hscl; + u32 inc_hscl; + u32 inc_vscl; + u32 en_mmp; + u32 scf_ch_core_gt; + u32 fmt; +} dss_scl_t; + +enum scl_coef_lut_idx { + SCL_COEF_NONE_IDX = -1, + SCL_COEF_YUV_IDX = 0, + SCL_COEF_RGB_IDX = 1, + SCL_COEF_IDX_MAX = 2, +}; + +/******************************************************************************* + ** ARSR2P v0 + */ +#define ARSR2P_INPUT_WIDTH_HEIGHT (0x000) +#define ARSR2P_OUTPUT_WIDTH_HEIGHT (0x004) +#define ARSR2P_IHLEFT (0x008) +#define ARSR2P_IHRIGHT (0x00C) +#define ARSR2P_IVTOP (0x010) +#define ARSR2P_IVBOTTOM (0x014) +#define ARSR2P_IHINC (0x018) +#define ARSR2P_IVINC (0x01C) +#define ARSR2P_UV_OFFSET (0x020) +#define ARSR2P_MODE (0x024) +#define ARSR2P_SKIN_THRES_Y (0x028) +#define ARSR2P_SKIN_THRES_U (0x02C) +#define ARSR2P_SKIN_THRES_V (0x030) +#define ARSR2P_SKIN_CFG0 (0x034) +#define ARSR2P_SKIN_CFG1 (0x038) +#define ARSR2P_SKIN_CFG2 (0x03C) +#define ARSR2P_SHOOT_CFG1 (0x040) +#define ARSR2P_SHOOT_CFG2 (0x044) +#define ARSR2P_SHARP_CFG1 (0x048) +#define ARSR2P_SHARP_CFG2 (0x04C) +#define ARSR2P_SHARP_CFG3 (0x050) +#define ARSR2P_SHARP_CFG4 (0x054) +#define ARSR2P_SHARP_CFG5 (0x058) +#define ARSR2P_SHARP_CFG6 (0x05C) +#define ARSR2P_SHARP_CFG7 (0x060) +#define ARSR2P_SHARP_CFG8 (0x064) +#define ARSR2P_SHARP_CFG9 (0x068) +#define ARSR2P_TEXTURW_ANALYSTS (0x06C) +#define ARSR2P_INTPLSHOOTCTRL (0x070) +#define ARSR2P_DEBUG0 (0x074) +#define ARSR2P_DEBUG1 (0x078) +#define ARSR2P_DEBUG2 (0x07C) +#define ARSR2P_DEBUG3 (0x080) +#define ARSR2P_LB_MEM_CTRL (0x084) +#define ARSR2P_IHLEFT1 (0x088) +#define ARSR2P_IHRIGHT1 (0x090) +#define ARSR2P_IVBOTTOM1 (0x094) + +#define ARSR2P_LUT_COEFY_V_OFFSET (0x0000) +#define ARSR2P_LUT_COEFY_H_OFFSET (0x0100) +#define ARSR2P_LUT_COEFA_V_OFFSET (0x0300) +#define ARSR2P_LUT_COEFA_H_OFFSET (0x0400) +#define ARSR2P_LUT_COEFUV_V_OFFSET (0x0600) +#define ARSR2P_LUT_COEFUV_H_OFFSET (0x0700) + +typedef struct dss_arsr2p_effect { + u32 skin_thres_y; + u32 skin_thres_u; + u32 skin_thres_v; + u32 skin_cfg0; + u32 skin_cfg1; + u32 skin_cfg2; + u32 shoot_cfg1; + u32 shoot_cfg2; + u32 sharp_cfg1; + u32 sharp_cfg2; + u32 sharp_cfg3; + u32 sharp_cfg4; + u32 sharp_cfg5; + u32 sharp_cfg6; + u32 sharp_cfg7; + u32 sharp_cfg8; + u32 sharp_cfg9; + u32 texturw_analysts; + u32 intplshootctrl; +} dss_arsr2p_effect_t; + +typedef struct dss_arsr2p { + u32 arsr_input_width_height; + u32 arsr_output_width_height; + u32 ihleft; + u32 ihright; + u32 ivtop; + u32 ivbottom; + u32 ihinc; + u32 ivinc; + u32 offset; + u32 mode; + dss_arsr2p_effect_t arsr2p_effect; + u32 ihleft1; + u32 ihright1; + u32 ivbottom1; +} dss_arsr2p_t; + +/******************************************************************************* + ** POST_CLIP v g + */ +#define POST_CLIP_DISP_SIZE (0x0000) +#define POST_CLIP_CTL_HRZ (0x0010) +#define POST_CLIP_CTL_VRZ (0x0014) +#define POST_CLIP_EN (0x0018) + +typedef struct dss_post_clip { + u32 disp_size; + u32 clip_ctl_hrz; + u32 clip_ctl_vrz; + u32 ctl_clip_en; +} dss_post_clip_t; + +/******************************************************************************* + ** PCSC v + */ +#define PCSC_IDC0 (0x0000) +#define PCSC_IDC2 (0x0004) +#define PCSC_ODC0 (0x0008) +#define PCSC_ODC2 (0x000C) +#define PCSC_P0 (0x0010) +#define PCSC_P1 (0x0014) +#define PCSC_P2 (0x0018) +#define PCSC_P3 (0x001C) +#define PCSC_P4 (0x0020) +#define PCSC_ICG_MODULE (0x0024) +#define PCSC_MPREC (0x0028) + +typedef struct dss_pcsc { + u32 pcsc_idc0; +} dss_pcsc_t; + +/******************************************************************************* + ** CSC + */ +#define CSC_IDC0 (0x0000) +#define CSC_IDC2 (0x0004) +#define CSC_ODC0 (0x0008) +#define CSC_ODC2 (0x000C) +#define CSC_P0 (0x0010) +#define CSC_P1 (0x0014) +#define CSC_P2 (0x0018) +#define CSC_P3 (0x001C) +#define CSC_P4 (0x0020) +#define CSC_ICG_MODULE (0x0024) +#define CSC_MPREC (0x0028) + +typedef struct dss_csc { + u32 idc0; + u32 idc2; + u32 odc0; + u32 odc2; + u32 p0; + u32 p1; + u32 p2; + u32 p3; + u32 p4; + u32 icg_module; + u32 mprec; +} dss_csc_t; + +/******************************************************************************* + **channel DEBUG + */ +#define CH_DEBUG_SEL (0x600) + +/******************************************************************************* + ** VPP + */ +#define VPP_CTRL (0x700) +#define VPP_MEM_CTRL (0x704) + +/******************************************************************************* + **DMA BUF + */ +#define DMA_BUF_CTRL (0x800) +#define DMA_BUF_SIZE (0x850) +#define DMA_BUF_MEM_CTRL (0x854) +#define DMA_BUF_DBG0 (0x0838) +#define DMA_BUF_DBG1 (0x083c) + +#define AFBCD_HREG_HDR_PTR_LO (0x900) +#define AFBCD_HREG_PIC_WIDTH (0x904) +#define AFBCD_HREG_PIC_HEIGHT (0x90C) +#define AFBCD_HREG_FORMAT (0x910) +#define AFBCD_CTL (0x914) +#define AFBCD_STR (0x918) +#define AFBCD_LINE_CROP (0x91C) +#define AFBCD_INPUT_HEADER_STRIDE (0x920) +#define AFBCD_PAYLOAD_STRIDE (0x924) +#define AFBCD_MM_BASE_0 (0x928) +#define AFBCD_AFBCD_PAYLOAD_POINTER (0x930) +#define AFBCD_HEIGHT_BF_STR (0x934) +#define AFBCD_OS_CFG (0x938) +#define AFBCD_MEM_CTRL (0x93C) +#define AFBCD_SCRAMBLE_MODE (0x940) +#define AFBCD_HEADER_POINTER_OFFSET (0x944) +#define AFBCD_MONITOR_REG1_OFFSET (0x948) +#define AFBCD_MONITOR_REG2_OFFSET (0x94C) +#define AFBCD_MONITOR_REG3_OFFSET (0x950) +#define AFBCD_DEBUG_REG0_OFFSET (0x954) + +#define AFBCE_HREG_PIC_BLKS (0x900) +#define AFBCE_HREG_FORMAT (0x904) +#define AFBCE_HREG_HDR_PTR_LO (0x908) +#define AFBCE_HREG_PLD_PTR_LO (0x90C) +#define AFBCE_PICTURE_SIZE (0x910) +#define AFBCE_CTL (0x914) +#define AFBCE_HEADER_SRTIDE (0x918) +#define AFBCE_PAYLOAD_STRIDE (0x91C) +#define AFBCE_ENC_OS_CFG (0x920) +#define AFBCE_MEM_CTRL (0x924) +#define AFBCE_QOS_CFG (0x928) +#define AFBCE_THRESHOLD (0x92C) +#define AFBCE_SCRAMBLE_MODE (0x930) +#define AFBCE_HEADER_POINTER_OFFSET (0x934) + +#define ROT_FIRST_LNS (0x530) +#define ROT_STATE (0x534) +#define ROT_MEM_CTRL (0x538) +#define ROT_SIZE (0x53C) +#define ROT_CPU_CTL0 (0x540) +#define ROT_CPU_START0 (0x544) +#define ROT_CPU_ADDR0 (0x548) +#define ROT_CPU_RDATA0 (0x54C) +#define ROT_CPU_RDATA1 (0x550) +#define ROT_CPU_WDATA0 (0x554) +#define ROT_CPU_WDATA1 (0x558) +#define ROT_CPU_CTL1 (0x55C) +#define ROT_CPU_START1 (0x560) +#define ROT_CPU_ADDR1 (0x564) +#define ROT_CPU_RDATA2 (0x568) +#define ROT_CPU_RDATA3 (0x56C) +#define ROT_CPU_WDATA2 (0x570) +#define ROT_CPU_WDATA3 (0x574) + +#define CH_REG_DEFAULT (0x0A00) + +/* MACROS */ +#define MIN_INTERLEAVE (7) +#define MAX_TILE_SURPORT_NUM (6) + +/* DMA aligned limited: 128bits aligned */ +#define DMA_ALIGN_BYTES (128 / BITS_PER_BYTE) +#define DMA_ADDR_ALIGN (128 / BITS_PER_BYTE) +#define DMA_STRIDE_ALIGN (128 / BITS_PER_BYTE) + +#define TILE_DMA_ADDR_ALIGN (256 * 1024) + +#define DMA_IN_WIDTH_MAX (2048) +#define DMA_IN_HEIGHT_MAX (8192) + +#define AFBC_PIC_WIDTH_MIN (16) +#define AFBC_PIC_WIDTH_MAX (8192) +#define AFBC_PIC_HEIGHT_MIN (16) +#define AFBC_PIC_HEIGHT_MAX (4096) + +#define AFBCD_TOP_CROP_MAX (15) +#define AFBCD_BOTTOM_CROP_MAX (15) + +#define AFBC_HEADER_STRIDE_BLOCK (16) + +#define AFBC_PAYLOAD_STRIDE_BLOCK (1024) + +#define AFBC_SUPER_GRAPH_HEADER_ADDR_ALIGN (128) +#define AFBC_HEADER_ADDR_ALIGN (64) +#define AFBC_HEADER_STRIDE_ALIGN (64) + +#define AFBC_PAYLOAD_ADDR_ALIGN_32 (1024) +#define AFBC_PAYLOAD_STRIDE_ALIGN_32 (1024) +#define AFBC_PAYLOAD_ADDR_ALIGN_16 (512) +#define AFBC_PAYLOAD_STRIDE_ALIGN_16 (512) + +#define AFBC_BLOCK_ALIGN (16) + +#define AFBCE_IN_WIDTH_MAX (512) +#define WROT_IN_WIDTH_MAX (512) + +#define MMBUF_BASE (0x40) +#define MMBUF_LINE_NUM (8) +#define MMBUF_ADDR_ALIGN (64) + +enum DSS_AFBC_HALF_BLOCK_MODE { + AFBC_HALF_BLOCK_UPPER_LOWER_ALL = 0, + AFBC_HALF_BLOCK_LOWER_UPPER_ALL, + AFBC_HALF_BLOCK_UPPER_ONLY, + AFBC_HALF_BLOCK_LOWER_ONLY, +}; + +typedef struct dss_rdma { + u32 oft_x0; + u32 oft_y0; + u32 oft_x1; + u32 oft_y1; + u32 mask0; + u32 mask1; + u32 stretch_size_vrt; + u32 ctrl; + u32 tile_scram; + + u32 data_addr0; + u32 stride0; + u32 stretch_stride0; + u32 data_num0; + + u32 data_addr1; + u32 stride1; + u32 stretch_stride1; + u32 data_num1; + + u32 data_addr2; + u32 stride2; + u32 stretch_stride2; + u32 data_num2; + + u32 ch_rd_shadow; + u32 ch_ctl; + + u32 dma_buf_ctrl; + + u32 vpp_ctrl; + u32 vpp_mem_ctrl; + + u32 afbcd_hreg_hdr_ptr_lo; + u32 afbcd_hreg_pic_width; + u32 afbcd_hreg_pic_height; + u32 afbcd_hreg_format; + u32 afbcd_ctl; + u32 afbcd_str; + u32 afbcd_line_crop; + u32 afbcd_input_header_stride; + u32 afbcd_payload_stride; + u32 afbcd_mm_base_0; + + u32 afbcd_afbcd_payload_pointer; + u32 afbcd_height_bf_str; + u32 afbcd_os_cfg; + u32 afbcd_mem_ctrl; + u32 afbcd_scramble_mode; + u32 afbcd_header_pointer_offset; + + u8 vpp_used; + u8 afbc_used; +} dss_rdma_t; + +typedef struct dss_wdma { + u32 oft_x0; + u32 oft_y0; + u32 oft_x1; + u32 oft_y1; + + u32 mask0; + u32 mask1; + u32 stretch_size_vrt; + u32 ctrl; + u32 tile_scram; + + u32 sw_mask_en; + u32 start_mask0; + u32 end_mask0; + u32 start_mask1; + u32 end_mask1; + + u32 data_addr; + u32 stride0; + u32 data1_addr; + u32 stride1; + + u32 stretch_stride; + u32 data_num; + + u32 ch_rd_shadow; + u32 ch_ctl; + u32 ch_secu_en; + u32 ch_sw_end_req; + + u32 dma_buf_ctrl; + u32 dma_buf_size; + + u32 rot_size; + + u32 afbce_hreg_pic_blks; + u32 afbce_hreg_format; + u32 afbce_hreg_hdr_ptr_lo; + u32 afbce_hreg_pld_ptr_lo; + u32 afbce_picture_size; + u32 afbce_ctl; + u32 afbce_header_srtide; + u32 afbce_payload_stride; + u32 afbce_enc_os_cfg; + u32 afbce_mem_ctrl; + u32 afbce_qos_cfg; + u32 afbce_threshold; + u32 afbce_scramble_mode; + u32 afbce_header_pointer_offset; + + u8 afbc_used; + u8 rot_used; +} dss_wdma_t; + +/******************************************************************************* + ** MCTL MUTEX0 1 2 3 4 5 + */ +#define MCTL_CTL_EN (0x0000) +#define MCTL_CTL_MUTEX (0x0004) +#define MCTL_CTL_MUTEX_STATUS (0x0008) +#define MCTL_CTL_MUTEX_ITF (0x000C) +#define MCTL_CTL_MUTEX_DBUF (0x0010) +#define MCTL_CTL_MUTEX_SCF (0x0014) +#define MCTL_CTL_MUTEX_OV (0x0018) +#define MCTL_CTL_MUTEX_WCH0 (0x0020) +#define MCTL_CTL_MUTEX_WCH1 (0x0024) +#define MCTL_CTL_MUTEX_WCH2 (0x0028) +#define MCTL_CTL_MUTEX_RCH8 (0x002C) +#define MCTL_CTL_MUTEX_RCH0 (0x0030) +#define MCTL_CTL_MUTEX_RCH1 (0x0034) +#define MCTL_CTL_MUTEX_RCH2 (0x0038) +#define MCTL_CTL_MUTEX_RCH3 (0x003C) +#define MCTL_CTL_MUTEX_RCH4 (0x0040) +#define MCTL_CTL_MUTEX_RCH5 (0x0044) +#define MCTL_CTL_MUTEX_RCH6 (0x0048) +#define MCTL_CTL_MUTEX_RCH7 (0x004C) +#define MCTL_CTL_TOP (0x0050) +#define MCTL_CTL_FLUSH_STATUS (0x0054) +#define MCTL_CTL_CLEAR (0x0058) +#define MCTL_CTL_CACK_TOUT (0x0060) +#define MCTL_CTL_MUTEX_TOUT (0x0064) +#define MCTL_CTL_STATUS (0x0068) +#define MCTL_CTL_INTEN (0x006C) +#define MCTL_CTL_SW_ST (0x0070) +#define MCTL_CTL_ST_SEL (0x0074) +#define MCTL_CTL_END_SEL (0x0078) +#define MCTL_CTL_CLK_SEL (0x0080) +#define MCTL_CTL_CLK_EN (0x0084) +#define MCTL_CTL_DBG (0x00E0) + +/******************************************************************************* + ** MCTL SYS + */ +#define MCTL_CTL_SECU_CFG (0x0000) +#define MCTL_PAY_SECU_FLUSH_EN (0x0018) +#define MCTL_CTL_SECU_GATE0 (0x0080) +#define MCTL_CTL_SECU_GATE1 (0x0084) +#define MCTL_CTL_SECU_GATE2 (0x0088) +#define MCTL_DSI0_SECU_CFG_EN (0x00A0) +#define MCTL_DSI1_SECU_CFG_EN (0x00A4) + +#define MCTL_RCH0_FLUSH_EN (0x0100) +#define MCTL_RCH1_FLUSH_EN (0x0104) +#define MCTL_RCH2_FLUSH_EN (0x0108) +#define MCTL_RCH3_FLUSH_EN (0x010C) +#define MCTL_RCH4_FLUSH_EN (0x0110) +#define MCTL_RCH5_FLUSH_EN (0x0114) +#define MCTL_RCH6_FLUSH_EN (0x0118) +#define MCTL_RCH7_FLUSH_EN (0x011C) +#define MCTL_WCH0_FLUSH_EN (0x0120) +#define MCTL_WCH1_FLUSH_EN (0x0124) +#define MCTL_OV0_FLUSH_EN (0x0128) +#define MCTL_OV1_FLUSH_EN (0x012C) +#define MCTL_OV2_FLUSH_EN (0x0130) +#define MCTL_OV3_FLUSH_EN (0x0134) +#define MCTL_RCH8_FLUSH_EN (0x0138) +#define MCTL_WCH2_FLUSH_EN (0x013C) + +#define MCTL_RCH0_OV_OEN (0x0160) +#define MCTL_RCH1_OV_OEN (0x0164) +#define MCTL_RCH2_OV_OEN (0x0168) +#define MCTL_RCH3_OV_OEN (0x016C) +#define MCTL_RCH4_OV_OEN (0x0170) +#define MCTL_RCH5_OV_OEN (0x0174) +#define MCTL_RCH6_OV_OEN (0x0178) +#define MCTL_RCH7_OV_OEN (0x017C) + +#define MCTL_RCH_OV0_SEL (0x0180) +#define MCTL_RCH_OV1_SEL (0x0184) +#define MCTL_RCH_OV2_SEL (0x0188) +#define MCTL_RCH_OV3_SEL (0x018C) + +#define MCTL_WCH0_OV_IEN (0x01A0) +#define MCTL_WCH1_OV_IEN (0x01A4) + +#define MCTL_WCH_OV2_SEL (0x01A8) +#define MCTL_WCH_OV3_SEL (0x01AC) + +#define MCTL_WB_ENC_SEL (0x01B0) +#define MCTL_DSI_MUX_SEL (0x01B4) + +#define MCTL_RCH0_STARTY (0x01C0) +#define MCTL_RCH1_STARTY (0x01C4) +#define MCTL_RCH2_STARTY (0x01C8) +#define MCTL_RCH3_STARTY (0x01CC) +#define MCTL_RCH4_STARTY (0x01D0) +#define MCTL_RCH5_STARTY (0x01D4) +#define MCTL_RCH6_STARTY (0x01D8) +#define MCTL_RCH7_STARTY (0x01DC) + +#define MCTL_MCTL_CLK_SEL (0x01F0) +#define MCTL_MCTL_CLK_EN (0x01F4) +#define MCTL_MOD_CLK_SEL (0x01F8) +#define MCTL_MOD_CLK_EN (0x01FC) + +#define MCTL_MOD0_DBG (0x0200) +#define MCTL_MOD1_DBG (0x0204) +#define MCTL_MOD2_DBG (0x0208) +#define MCTL_MOD3_DBG (0x020C) +#define MCTL_MOD4_DBG (0x0210) +#define MCTL_MOD5_DBG (0x0214) +#define MCTL_MOD6_DBG (0x0218) +#define MCTL_MOD7_DBG (0x021C) +#define MCTL_MOD8_DBG (0x0220) +#define MCTL_MOD9_DBG (0x0224) +#define MCTL_MOD10_DBG (0x0228) +#define MCTL_MOD11_DBG (0x022C) +#define MCTL_MOD12_DBG (0x0230) +#define MCTL_MOD13_DBG (0x0234) +#define MCTL_MOD14_DBG (0x0238) +#define MCTL_MOD15_DBG (0x023C) +#define MCTL_MOD16_DBG (0x0240) +#define MCTL_MOD17_DBG (0x0244) +#define MCTL_MOD18_DBG (0x0248) +#define MCTL_MOD19_DBG (0x024C) +#define MCTL_MOD20_DBG (0x0250) +#define MCTL_MOD0_STATUS (0x0280) +#define MCTL_MOD1_STATUS (0x0284) +#define MCTL_MOD2_STATUS (0x0288) +#define MCTL_MOD3_STATUS (0x028C) +#define MCTL_MOD4_STATUS (0x0290) +#define MCTL_MOD5_STATUS (0x0294) +#define MCTL_MOD6_STATUS (0x0298) +#define MCTL_MOD7_STATUS (0x029C) +#define MCTL_MOD8_STATUS (0x02A0) +#define MCTL_MOD9_STATUS (0x02A4) +#define MCTL_MOD10_STATUS (0x02A8) +#define MCTL_MOD11_STATUS (0x02AC) +#define MCTL_MOD12_STATUS (0x02B0) +#define MCTL_MOD13_STATUS (0x02B4) +#define MCTL_MOD14_STATUS (0x02B8) +#define MCTL_MOD15_STATUS (0x02BC) +#define MCTL_MOD16_STATUS (0x02C0) +#define MCTL_MOD17_STATUS (0x02C4) +#define MCTL_MOD18_STATUS (0x02C8) +#define MCTL_MOD19_STATUS (0x02CC) +#define MCTL_MOD20_STATUS (0x02D0) +#define MCTL_SW_DBG (0x0300) +#define MCTL_SW0_STATUS0 (0x0304) +#define MCTL_SW0_STATUS1 (0x0308) +#define MCTL_SW0_STATUS2 (0x030C) +#define MCTL_SW0_STATUS3 (0x0310) +#define MCTL_SW0_STATUS4 (0x0314) +#define MCTL_SW0_STATUS5 (0x0318) +#define MCTL_SW0_STATUS6 (0x031C) +#define MCTL_SW0_STATUS7 (0x0320) +#define MCTL_SW1_STATUS (0x0324) + +#define MCTL_MOD_DBG_CH_NUM (10) +#define MCTL_MOD_DBG_OV_NUM (4) +#define MCTL_MOD_DBG_DBUF_NUM (2) +#define MCTL_MOD_DBG_SCF_NUM (1) +#define MCTL_MOD_DBG_ITF_NUM (2) +#define MCTL_MOD_DBG_ADD_CH_NUM (2) + +enum dss_mctl_idx { + DSS_MCTL0 = 0, + DSS_MCTL1, + DSS_MCTL2, + DSS_MCTL3, + DSS_MCTL4, + DSS_MCTL5, + DSS_MCTL_IDX_MAX, +}; + +typedef struct dss_mctl { + u32 ctl_mutex_itf; + u32 ctl_mutex_dbuf; + u32 ctl_mutex_scf; + u32 ctl_mutex_ov; +} dss_mctl_t; + +typedef struct dss_mctl_ch_base { + char __iomem *chn_mutex_base; + char __iomem *chn_flush_en_base; + char __iomem *chn_ov_en_base; + char __iomem *chn_starty_base; + char __iomem *chn_mod_dbg_base; +} dss_mctl_ch_base_t; + +typedef struct dss_mctl_ch { + u32 chn_mutex; + u32 chn_flush_en; + u32 chn_ov_oen; + u32 chn_starty; + u32 chn_mod_dbg; +} dss_mctl_ch_t; + +typedef struct dss_mctl_sys { + u32 ov_flush_en[DSS_OVL_IDX_MAX]; + u32 chn_ov_sel[DSS_OVL_IDX_MAX]; + u32 wchn_ov_sel[DSS_WCH_MAX]; + u8 ov_flush_en_used[DSS_OVL_IDX_MAX]; + u8 chn_ov_sel_used[DSS_OVL_IDX_MAX]; + u8 wch_ov_sel_used[DSS_WCH_MAX]; +} dss_mctl_sys_t; + +/******************************************************************************* + ** OVL + */ +#define OVL_SIZE (0x0000) +#define OVL_BG_COLOR (0x4) +#define OVL_DST_STARTPOS (0x8) +#define OVL_DST_ENDPOS (0xC) +#define OVL_GCFG (0x10) +#define OVL_LAYER0_POS (0x14) +#define OVL_LAYER0_SIZE (0x18) +#define OVL_LAYER0_SRCLOKEY (0x1C) +#define OVL_LAYER0_SRCHIKEY (0x20) +#define OVL_LAYER0_DSTLOKEY (0x24) +#define OVL_LAYER0_DSTHIKEY (0x28) +#define OVL_LAYER0_PATTERN (0x2C) +#define OVL_LAYER0_ALPHA (0x30) +#define OVL_LAYER0_CFG (0x34) +#define OVL_LAYER0_INFO_ALPHA (0x40) +#define OVL_LAYER0_INFO_SRCCOLOR (0x44) +#define OVL_LAYER1_POS (0x50) +#define OVL_LAYER1_SIZE (0x54) +#define OVL_LAYER1_SRCLOKEY (0x58) +#define OVL_LAYER1_SRCHIKEY (0x5C) +#define OVL_LAYER1_DSTLOKEY (0x60) +#define OVL_LAYER1_DSTHIKEY (0x64) +#define OVL_LAYER1_PATTERN (0x68) +#define OVL_LAYER1_ALPHA (0x6C) +#define OVL_LAYER1_CFG (0x70) +#define OVL_LAYER1_INFO_ALPHA (0x7C) +#define OVL_LAYER1_INFO_SRCCOLOR (0x80) +#define OVL_LAYER2_POS (0x8C) +#define OVL_LAYER2_SIZE (0x90) +#define OVL_LAYER2_SRCLOKEY (0x94) +#define OVL_LAYER2_SRCHIKEY (0x98) +#define OVL_LAYER2_DSTLOKEY (0x9C) +#define OVL_LAYER2_DSTHIKEY (0xA0) +#define OVL_LAYER2_PATTERN (0xA4) +#define OVL_LAYER2_ALPHA (0xA8) +#define OVL_LAYER2_CFG (0xAC) +#define OVL_LAYER2_INFO_ALPHA (0xB8) +#define OVL_LAYER2_INFO_SRCCOLOR (0xBC) +#define OVL_LAYER3_POS (0xC8) +#define OVL_LAYER3_SIZE (0xCC) +#define OVL_LAYER3_SRCLOKEY (0xD0) +#define OVL_LAYER3_SRCHIKEY (0xD4) +#define OVL_LAYER3_DSTLOKEY (0xD8) +#define OVL_LAYER3_DSTHIKEY (0xDC) +#define OVL_LAYER3_PATTERN (0xE0) +#define OVL_LAYER3_ALPHA (0xE4) +#define OVL_LAYER3_CFG (0xE8) +#define OVL_LAYER3_INFO_ALPHA (0xF4) +#define OVL_LAYER3_INFO_SRCCOLOR (0xF8) +#define OVL_LAYER4_POS (0x104) +#define OVL_LAYER4_SIZE (0x108) +#define OVL_LAYER4_SRCLOKEY (0x10C) +#define OVL_LAYER4_SRCHIKEY (0x110) +#define OVL_LAYER4_DSTLOKEY (0x114) +#define OVL_LAYER4_DSTHIKEY (0x118) +#define OVL_LAYER4_PATTERN (0x11C) +#define OVL_LAYER4_ALPHA (0x120) +#define OVL_LAYER4_CFG (0x124) +#define OVL_LAYER4_INFO_ALPHA (0x130) +#define OVL_LAYER4_INFO_SRCCOLOR (0x134) +#define OVL_LAYER5_POS (0x140) +#define OVL_LAYER5_SIZE (0x144) +#define OVL_LAYER5_SRCLOKEY (0x148) +#define OVL_LAYER5_SRCHIKEY (0x14C) +#define OVL_LAYER5_DSTLOKEY (0x150) +#define OVL_LAYER5_DSTHIKEY (0x154) +#define OVL_LAYER5_PATTERN (0x158) +#define OVL_LAYER5_ALPHA (0x15C) +#define OVL_LAYER5_CFG (0x160) +#define OVL_LAYER5_INFO_ALPHA (0x16C) +#define OVL_LAYER5_INFO_SRCCOLOR (0x170) +#define OVL_LAYER6_POS (0x14) +#define OVL_LAYER6_SIZE (0x18) +#define OVL_LAYER6_SRCLOKEY (0x1C) +#define OVL_LAYER6_SRCHIKEY (0x20) +#define OVL_LAYER6_DSTLOKEY (0x24) +#define OVL_LAYER6_DSTHIKEY (0x28) +#define OVL_LAYER6_PATTERN (0x2C) +#define OVL_LAYER6_ALPHA (0x30) +#define OVL_LAYER6_CFG (0x34) +#define OVL_LAYER6_INFO_ALPHA (0x40) +#define OVL_LAYER6_INFO_SRCCOLOR (0x44) +#define OVL_LAYER7_POS (0x50) +#define OVL_LAYER7_SIZE (0x54) +#define OVL_LAYER7_SRCLOKEY (0x58) +#define OVL_LAYER7_SRCHIKEY (0x5C) +#define OVL_LAYER7_DSTLOKEY (0x60) +#define OVL_LAYER7_DSTHIKEY (0x64) +#define OVL_LAYER7_PATTERN (0x68) +#define OVL_LAYER7_ALPHA (0x6C) +#define OVL_LAYER7_CFG (0x70) +#define OVL_LAYER7_INFO_ALPHA (0x7C) +#define OVL_LAYER7_INFO_SRCCOLOR (0x80) +#define OVL_LAYER0_ST_INFO (0x48) +#define OVL_LAYER1_ST_INFO (0x84) +#define OVL_LAYER2_ST_INFO (0xC0) +#define OVL_LAYER3_ST_INFO (0xFC) +#define OVL_LAYER4_ST_INFO (0x138) +#define OVL_LAYER5_ST_INFO (0x174) +#define OVL_LAYER6_ST_INFO (0x48) +#define OVL_LAYER7_ST_INFO (0x84) +#define OVL_LAYER0_IST_INFO (0x4C) +#define OVL_LAYER1_IST_INFO (0x88) +#define OVL_LAYER2_IST_INFO (0xC4) +#define OVL_LAYER3_IST_INFO (0x100) +#define OVL_LAYER4_IST_INFO (0x13C) +#define OVL_LAYER5_IST_INFO (0x178) +#define OVL_LAYER6_IST_INFO (0x4C) +#define OVL_LAYER7_IST_INFO (0x88) +#define OVL_LAYER0_PSPOS (0x38) +#define OVL_LAYER0_PEPOS (0x3C) +#define OVL_LAYER1_PSPOS (0x74) +#define OVL_LAYER1_PEPOS (0x78) +#define OVL_LAYER2_PSPOS (0xB0) +#define OVL_LAYER2_PEPOS (0xB4) +#define OVL_LAYER3_PSPOS (0xEC) +#define OVL_LAYER3_PEPOS (0xF0) +#define OVL_LAYER4_PSPOS (0x128) +#define OVL_LAYER4_PEPOS (0x12C) +#define OVL_LAYER5_PSPOS (0x164) +#define OVL_LAYER5_PEPOS (0x168) +#define OVL_LAYER6_PSPOS (0x38) +#define OVL_LAYER6_PEPOS (0x3C) +#define OVL_LAYER7_PSPOS (0x74) +#define OVL_LAYER7_PEPOS (0x78) + +#define OVL6_BASE_ST_INFO (0x17C) +#define OVL6_BASE_IST_INFO (0x180) +#define OVL6_GATE_CTRL (0x184) +#define OVL6_RD_SHADOW_SEL (0x188) +#define OVL6_OV_CLK_SEL (0x18C) +#define OVL6_OV_CLK_EN (0x190) +#define OVL6_BLOCK_SIZE (0x1A0) +#define OVL6_BLOCK_DBG (0x1A4) +#define OVL6_REG_DEFAULT (0x1A8) + +#define OVL2_BASE_ST_INFO (0x8C) +#define OVL2_BASE_IST_INFO (0x90) +#define OVL2_GATE_CTRL (0x94) +#define OVL2_OV_RD_SHADOW_SEL (0x98) +#define OVL2_OV_CLK_SEL (0x9C) +#define OVL2_OV_CLK_EN (0xA0) +#define OVL2_BLOCK_SIZE (0xB0) +#define OVL2_BLOCK_DBG (0xB4) +#define OVL2_REG_DEFAULT (0xB8) + +/* LAYER0_CFG */ +#define BIT_OVL_LAYER_SRC_CFG BIT(8) +#define BIT_OVL_LAYER_ENABLE BIT(0) + +/* LAYER0_INFO_ALPHA */ +#define BIT_OVL_LAYER_SRCALPHA_FLAG BIT(3) +#define BIT_OVL_LAYER_DSTALPHA_FLAG BIT(2) + +/* LAYER0_INFO_SRCCOLOR */ +#define BIT_OVL_LAYER_SRCCOLOR_FLAG BIT(0) + +#define OVL_6LAYER_NUM (6) +#define OVL_2LAYER_NUM (2) + +typedef struct dss_ovl_layer { + u32 layer_pos; + u32 layer_size; + u32 layer_pattern; + u32 layer_alpha; + u32 layer_cfg; + +} dss_ovl_layer_t; + +typedef struct dss_ovl_layer_pos { + u32 layer_pspos; + u32 layer_pepos; + +} dss_ovl_layer_pos_t; + +typedef struct dss_ovl { + u32 ovl_size; + u32 ovl_bg_color; + u32 ovl_dst_startpos; + u32 ovl_dst_endpos; + u32 ovl_gcfg; + u32 ovl_block_size; + dss_ovl_layer_t ovl_layer[OVL_6LAYER_NUM]; + dss_ovl_layer_pos_t ovl_layer_pos[OVL_6LAYER_NUM]; + u8 ovl_layer_used[OVL_6LAYER_NUM]; +} dss_ovl_t; + +typedef struct dss_ovl_alpha { + u32 src_amode; + u32 src_gmode; + u32 alpha_offsrc; + u32 src_lmode; + u32 src_pmode; + + u32 alpha_smode; + + u32 dst_amode; + u32 dst_gmode; + u32 alpha_offdst; + u32 dst_pmode; + + u32 fix_mode; +} dss_ovl_alpha_t; + +/******************************************************************************* + ** DBUF + */ +#define DBUF_FRM_SIZE (0x0000) +#define DBUF_FRM_HSIZE (0x0004) +#define DBUF_SRAM_VALID_NUM (0x0008) +#define DBUF_WBE_EN (0x000C) +#define DBUF_THD_FILL_LEV0 (0x0010) +#define DBUF_DFS_FILL_LEV1 (0x0014) +#define DBUF_THD_RQOS (0x0018) +#define DBUF_THD_WQOS (0x001C) +#define DBUF_THD_CG (0x0020) +#define DBUF_THD_OTHER (0x0024) +#define DBUF_FILL_LEV0_CNT (0x0028) +#define DBUF_FILL_LEV1_CNT (0x002C) +#define DBUF_FILL_LEV2_CNT (0x0030) +#define DBUF_FILL_LEV3_CNT (0x0034) +#define DBUF_FILL_LEV4_CNT (0x0038) +#define DBUF_ONLINE_FILL_LEVEL (0x003C) +#define DBUF_WB_FILL_LEVEL (0x0040) +#define DBUF_DFS_STATUS (0x0044) +#define DBUF_THD_FLUX_REQ_BEF (0x0048) +#define DBUF_DFS_LP_CTRL (0x004C) +#define DBUF_RD_SHADOW_SEL (0x0050) +#define DBUF_MEM_CTRL (0x0054) +#define DBUF_PM_CTRL (0x0058) +#define DBUF_CLK_SEL (0x005C) +#define DBUF_CLK_EN (0x0060) +#define DBUF_THD_FLUX_REQ_AFT (0x0064) +#define DBUF_THD_DFS_OK (0x0068) +#define DBUF_FLUX_REQ_CTRL (0x006C) +#define DBUF_REG_DEFAULT (0x00A4) + +/******************************************************************************* + ** DPP + */ +#define DPP_RD_SHADOW_SEL (0x000) +#define DPP_DEFAULT (0x004) +#define DPP_ID (0x008) +#define DPP_IMG_SIZE_BEF_SR (0x00C) +#define DPP_IMG_SIZE_AFT_SR (0x010) +#define DPP_SBL (0x014) +#define DPP_SBL_MEM_CTRL (0x018) +#define DPP_ARSR1P_MEM_CTRL (0x01C) +#define DPP_CLK_SEL (0x020) +#define DPP_CLK_EN (0x024) +#define DPP_DBG1_CNT (0x028) +#define DPP_DBG2_CNT (0x02C) +#define DPP_DBG1 (0x030) +#define DPP_DBG2 (0x034) +#define DPP_DBG3 (0x038) +#define DPP_DBG4 (0x03C) +#define DPP_INTS (0x040) +#define DPP_INT_MSK (0x044) +#define DPP_ARSR1P (0x048) +#define DPP_DBG_CNT DPP_DBG1_CNT + +#define DPP_CLRBAR_CTRL (0x100) +#define DPP_CLRBAR_1ST_CLR (0x104) +#define DPP_CLRBAR_2ND_CLR (0x108) +#define DPP_CLRBAR_3RD_CLR (0x10C) + +#define DPP_CLIP_TOP (0x180) +#define DPP_CLIP_BOTTOM (0x184) +#define DPP_CLIP_LEFT (0x188) +#define DPP_CLIP_RIGHT (0x18C) +#define DPP_CLIP_EN (0x190) +#define DPP_CLIP_DBG (0x194) + +#define DITHER_PARA (0x000) +#define DITHER_CTL (0x004) +#define DITHER_MATRIX_PART1 (0x008) +#define DITHER_MATRIX_PART0 (0x00C) +#define DITHER_ERRDIFF_WEIGHT (0x010) +#define DITHER_FRC_01_PART1 (0x014) +#define DITHER_FRC_01_PART0 (0x018) +#define DITHER_FRC_10_PART1 (0x01C) +#define DITHER_FRC_10_PART0 (0x020) +#define DITHER_FRC_11_PART1 (0x024) +#define DITHER_FRC_11_PART0 (0x028) +#define DITHER_MEM_CTRL (0x02C) +#define DITHER_DBG0 (0x030) +#define DITHER_DBG1 (0x034) +#define DITHER_DBG2 (0x038) + +#define CSC10B_IDC0 (0x000) +#define CSC10B_IDC1 (0x004) +#define CSC10B_IDC2 (0x008) +#define CSC10B_ODC0 (0x00C) +#define CSC10B_ODC1 (0x010) +#define CSC10B_ODC2 (0x014) +#define CSC10B_P00 (0x018) +#define CSC10B_P01 (0x01C) +#define CSC10B_P02 (0x020) +#define CSC10B_P10 (0x024) +#define CSC10B_P11 (0x028) +#define CSC10B_P12 (0x02C) +#define CSC10B_P20 (0x030) +#define CSC10B_P21 (0x034) +#define CSC10B_P22 (0x038) +#define CSC10B_MODULE_EN (0x03C) +#define CSC10B_MPREC (0x040) + +#define GAMA_EN (0x000) +#define GAMA_MEM_CTRL (0x004) + +#define ACM_EN (0x000) +#define ACM_SATA_OFFSET (0x004) +#define ACM_HUESEL (0x008) +#define ACM_CSC_IDC0 (0x00C) +#define ACM_CSC_IDC1 (0x010) +#define ACM_CSC_IDC2 (0x014) +#define ACM_CSC_P00 (0x018) +#define ACM_CSC_P01 (0x01C) +#define ACM_CSC_P02 (0x020) +#define ACM_CSC_P10 (0x024) +#define ACM_CSC_P11 (0x028) +#define ACM_CSC_P12 (0x02C) +#define ACM_CSC_P20 (0x030) +#define ACM_CSC_P21 (0x034) +#define ACM_CSC_P22 (0x038) +#define ACM_CSC_MRREC (0x03C) +#define ACM_R0_H (0x040) +#define ACM_R1_H (0x044) +#define ACM_R2_H (0x048) +#define ACM_R3_H (0x04C) +#define ACM_R4_H (0x050) +#define ACM_R5_H (0x054) +#define ACM_R6_H (0x058) +#define ACM_LUT_DIS0 (0x05C) +#define ACM_LUT_DIS1 (0x060) +#define ACM_LUT_DIS2 (0x064) +#define ACM_LUT_DIS3 (0x068) +#define ACM_LUT_DIS4 (0x06C) +#define ACM_LUT_DIS5 (0x070) +#define ACM_LUT_DIS6 (0x074) +#define ACM_LUT_DIS7 (0x078) +#define ACM_LUT_PARAM0 (0x07C) +#define ACM_LUT_PARAM1 (0x080) +#define ACM_LUT_PARAM2 (0x084) +#define ACM_LUT_PARAM3 (0x088) +#define ACM_LUT_PARAM4 (0x08C) +#define ACM_LUT_PARAM5 (0x090) +#define ACM_LUT_PARAM6 (0x094) +#define ACM_LUT_PARAM7 (0x098) +#define ACM_LUT_SEL (0x09C) +#define ACM_MEM_CTRL (0x0A0) +#define ACM_DEBUG_TOP (0x0A4) +#define ACM_DEBUG_CFG (0x0A8) +#define ACM_DEBUG_W (0x0AC) + +#define ACE_EN (0x000) +#define ACE_SKIN_CFG (0x004) +#define ACE_LUT_SEL (0x008) +#define ACE_HIST_IND (0x00C) +#define ACE_ACTIVE (0x010) +#define ACE_DBG (0x014) +#define ACE_MEM_CTRL (0x018) +#define ACE_IN_SEL (0x01C) +#define ACE_R2Y (0x020) +#define ACE_G2Y (0x024) +#define ACE_B2Y (0x028) +#define ACE_Y_OFFSET (0x02C) +#define ACE_Y_CEN (0x030) +#define ACE_U_CEN (0x034) +#define ACE_V_CEN (0x038) +#define ACE_Y_EXT (0x03C) +#define ACE_U_EXT (0x040) +#define ACE_V_EXT (0x044) +#define ACE_Y_ATTENU (0x048) +#define ACE_U_ATTENU (0x04C) +#define ACE_V_ATTENU (0x050) +#define ACE_ROTA (0x054) +#define ACE_ROTB (0x058) +#define ACE_Y_CORE (0x05C) +#define ACE_U_CORE (0x060) +#define ACE_V_CORE (0x064) + +#define LCP_XCC_COEF_00 (0x000) +#define LCP_XCC_COEF_01 (0x004) +#define LCP_XCC_COEF_02 (0x008) +#define LCP_XCC_COEF_03 (0x00C) +#define LCP_XCC_COEF_10 (0x010) +#define LCP_XCC_COEF_11 (0x014) +#define LCP_XCC_COEF_12 (0x018) +#define LCP_XCC_COEF_13 (0x01C) +#define LCP_XCC_COEF_20 (0x020) +#define LCP_XCC_COEF_21 (0x024) +#define LCP_XCC_COEF_22 (0x028) +#define LCP_XCC_COEF_23 (0x02C) +#define LCP_GMP_BYPASS_EN (0x030) +#define LCP_XCC_BYPASS_EN (0x034) +#define LCP_DEGAMA_EN (0x038) +#define LCP_DEGAMA_MEM_CTRL (0x03C) +#define LCP_GMP_MEM_CTRL (0x040) + +typedef struct dss_arsr1p { + u32 ihleft; + u32 ihright; + u32 ihleft1; + u32 ihright1; + u32 ivtop; + u32 ivbottom; + u32 uv_offset; + u32 ihinc; + u32 ivinc; + u32 mode; + u32 format; + + u32 skin_thres_y; + u32 skin_thres_u; + u32 skin_thres_v; + u32 skin_expected; + u32 skin_cfg; + u32 shoot_cfg1; + u32 shoot_cfg2; + u32 sharp_cfg1; + u32 sharp_cfg2; + u32 sharp_cfg3; + u32 sharp_cfg4; + u32 sharp_cfg5; + u32 sharp_cfg6; + u32 sharp_cfg7; + u32 sharp_cfg8; + u32 sharp_cfg9; + u32 sharp_cfg10; + u32 sharp_cfg11; + u32 diff_ctrl; + u32 lsc_cfg1; + u32 lsc_cfg2; + u32 lsc_cfg3; + u32 force_clk_on_cfg; + + u32 dpp_img_hrz_bef_sr; + u32 dpp_img_vrt_bef_sr; + u32 dpp_img_hrz_aft_sr; + u32 dpp_img_vrt_aft_sr; +} dss_arsr1p_t; + +#define ARSR1P_INC_FACTOR (65536) + +#define ARSR1P_IHLEFT (0x000) +#define ARSR1P_IHRIGHT (0x004) +#define ARSR1P_IHLEFT1 (0x008) +#define ARSR1P_IHRIGHT1 (0x00C) +#define ARSR1P_IVTOP (0x010) +#define ARSR1P_IVBOTTOM (0x014) +#define ARSR1P_UV_OFFSET (0x018) +#define ARSR1P_IHINC (0x01C) +#define ARSR1P_IVINC (0x020) +#define ARSR1P_MODE (0x024) +#define ARSR1P_FORMAT (0x028) +#define ARSR1P_SKIN_THRES_Y (0x02C) +#define ARSR1P_SKIN_THRES_U (0x030) +#define ARSR1P_SKIN_THRES_V (0x034) +#define ARSR1P_SKIN_EXPECTED (0x038) +#define ARSR1P_SKIN_CFG (0x03C) +#define ARSR1P_SHOOT_CFG1 (0x040) +#define ARSR1P_SHOOT_CFG2 (0x044) +#define ARSR1P_SHARP_CFG1 (0x048) +#define ARSR1P_SHARP_CFG2 (0x04C) +#define ARSR1P_SHARP_CFG3 (0x050) +#define ARSR1P_SHARP_CFG4 (0x054) +#define ARSR1P_SHARP_CFG5 (0x058) +#define ARSR1P_SHARP_CFG6 (0x05C) +#define ARSR1P_SHARP_CFG7 (0x060) +#define ARSR1P_SHARP_CFG8 (0x064) +#define ARSR1P_SHARP_CFG9 (0x068) +#define ARSR1P_SHARP_CFG10 (0x06C) +#define ARSR1P_SHARP_CFG11 (0x070) +#define ARSR1P_DIFF_CTRL (0x074) +#define ARSR1P_LSC_CFG1 (0x078) +#define ARSR1P_LSC_CFG2 (0x07C) +#define ARSR1P_LSC_CFG3 (0x080) +#define ARSR1P_FORCE_CLK_ON_CFG (0x084) + +/******************************************************************************* + ** BIT EXT + */ +#define BIT_EXT0_CTL (0x000) + +#define U_GAMA_R_COEF (0x000) +#define U_GAMA_G_COEF (0x400) +#define U_GAMA_B_COEF (0x800) +#define U_GAMA_R_LAST_COEF (0x200) +#define U_GAMA_G_LAST_COEF (0x600) +#define U_GAMA_B_LAST_COEF (0xA00) + +#define ACM_U_H_COEF (0x000) +#define ACM_U_SATA_COEF (0x200) +#define ACM_U_SATR0_COEF (0x300) +#define ACM_U_SATR1_COEF (0x340) +#define ACM_U_SATR2_COEF (0x380) +#define ACM_U_SATR3_COEF (0x3C0) +#define ACM_U_SATR4_COEF (0x400) +#define ACM_U_SATR5_COEF (0x440) +#define ACM_U_SATR6_COEF (0x480) +#define ACM_U_SATR7_COEF (0x4C0) + +#define LCP_U_GMP_COEF (0x0000) +#define LCP_U_DEGAMA_R_COEF (0x5000) +#define LCP_U_DEGAMA_G_COEF (0x5400) +#define LCP_U_DEGAMA_B_COEF (0x5800) +#define LCP_U_DEGAMA_R_LAST_COEF (0x5200) +#define LCP_U_DEGAMA_G_LAST_COEF (0x5600) +#define LCP_U_DEGAMA_B_LAST_COEF (0x5A00) + +#define ACE_HIST0 (0x000) +#define ACE_HIST1 (0x400) +#define ACE_LUT0 (0x800) +#define ACE_LUT1 (0xA00) + +#define ARSR1P_LSC_GAIN (0x084) +#define ARSR1P_COEFF_H_Y0 (0x0F0) +#define ARSR1P_COEFF_H_Y1 (0x114) +#define ARSR1P_COEFF_V_Y0 (0x138) +#define ARSR1P_COEFF_V_Y1 (0x15C) +#define ARSR1P_COEFF_H_UV0 (0x180) +#define ARSR1P_COEFF_H_UV1 (0x1A4) +#define ARSR1P_COEFF_V_UV0 (0x1C8) +#define ARSR1P_COEFF_V_UV1 (0x1EC) + +#define HIACE_INT_STAT (0x0000) +#define HIACE_INT_UNMASK (0x0004) +#define HIACE_BYPASS_ACE (0x0008) +#define HIACE_BYPASS_ACE_STAT (0x000c) +#define HIACE_UPDATE_LOCAL (0x0010) +#define HIACE_LOCAL_VALID (0x0014) +#define HIACE_GAMMA_AB_SHADOW (0x0018) +#define HIACE_GAMMA_AB_WORK (0x001c) +#define HIACE_GLOBAL_HIST_AB_SHADOW (0x0020) +#define HIACE_GLOBAL_HIST_AB_WORK (0x0024) +#define HIACE_IMAGE_INFO (0x0030) +#define HIACE_HALF_BLOCK_H_W (0x0034) +#define HIACE_XYWEIGHT (0x0038) +#define HIACE_LHIST_SFT (0x003c) +#define HIACE_HUE (0x0050) +#define HIACE_SATURATION (0x0054) +#define HIACE_VALUE (0x0058) +#define HIACE_SKIN_GAIN (0x005c) +#define HIACE_UP_LOW_TH (0x0060) +#define HIACE_UP_CNT (0x0070) +#define HIACE_LOW_CNT (0x0074) +#define HIACE_GLOBAL_HIST_LUT_ADDR (0x0080) +#define HIACE_LHIST_EN (0x0100) +#define HIACE_LOCAL_HIST_VxHy_2z_2z1 (0x0104) +#define HIACE_GAMMA_EN (0x0108) +#define HIACE_GAMMA_VxHy_3z2_3z1_3z_W (0x010c) +#define HIACE_GAMMA_EN_HV_R (0x0110) +#define HIACE_GAMMA_VxHy_3z2_3z1_3z_R (0x0114) +#define HIACE_INIT_GAMMA (0x0120) +#define HIACE_MANUAL_RELOAD (0x0124) +#define HIACE_RAMCLK_FUNC (0x0128) +#define HIACE_CLK_GATE (0x012c) +#define HIACE_GAMMA_RAM_A_CFG_MEM_CTRL (0x0130) +#define HIACE_GAMMA_RAM_B_CFG_MEM_CTRL (0x0134) +#define HIACE_LHIST_RAM_CFG_MEM_CTRL (0x0138) +#define HIACE_GAMMA_RAM_A_CFG_PM_CTRL (0x0140) +#define HIACE_GAMMA_RAM_B_CFG_PM_CTRL (0x0144) +#define HIACE_LHIST_RAM_CFG_PM_CTRL (0x0148) + +/******************************************************************************* + ** IFBC + */ +#define IFBC_SIZE (0x0000) +#define IFBC_CTRL (0x0004) +#define IFBC_HIMAX_CTRL0 (0x0008) +#define IFBC_HIMAX_CTRL1 (0x000C) +#define IFBC_HIMAX_CTRL2 (0x0010) +#define IFBC_HIMAX_CTRL3 (0x0014) +#define IFBC_EN (0x0018) +#define IFBC_MEM_CTRL (0x001C) +#define IFBC_INSERT (0x0020) +#define IFBC_HIMAX_TEST_MODE (0x0024) +#define IFBC_CORE_GT (0x0028) +#define IFBC_PM_CTRL (0x002C) +#define IFBC_RD_SHADOW (0x0030) +#define IFBC_ORISE_CTL (0x0034) +#define IFBC_ORSISE_DEBUG0 (0x0038) +#define IFBC_ORSISE_DEBUG1 (0x003C) +#define IFBC_RSP_COMP_TEST (0x0040) +#define IFBC_CLK_SEL (0x044) +#define IFBC_CLK_EN (0x048) +#define IFBC_PAD (0x004C) +#define IFBC_REG_DEFAULT (0x0050) + +/******************************************************************************* + ** DSC + */ +#define DSC_VERSION (0x0000) +#define DSC_PPS_IDENTIFIER (0x0004) +#define DSC_EN (0x0008) +#define DSC_CTRL (0x000C) +#define DSC_PIC_SIZE (0x0010) +#define DSC_SLICE_SIZE (0x0014) +#define DSC_CHUNK_SIZE (0x0018) +#define DSC_INITIAL_DELAY (0x001C) +#define DSC_RC_PARAM0 (0x0020) +#define DSC_RC_PARAM1 (0x0024) +#define DSC_RC_PARAM2 (0x0028) +#define DSC_RC_PARAM3 (0x002C) +#define DSC_FLATNESS_QP_TH (0x0030) +#define DSC_RC_PARAM4 (0x0034) +#define DSC_RC_PARAM5 (0x0038) +#define DSC_RC_BUF_THRESH0 (0x003C) +#define DSC_RC_BUF_THRESH1 (0x0040) +#define DSC_RC_BUF_THRESH2 (0x0044) +#define DSC_RC_BUF_THRESH3 (0x0048) +#define DSC_RC_RANGE_PARAM0 (0x004C) +#define DSC_RC_RANGE_PARAM1 (0x0050) +#define DSC_RC_RANGE_PARAM2 (0x0054) +#define DSC_RC_RANGE_PARAM3 (0x0058) +#define DSC_RC_RANGE_PARAM4 (0x005C) +#define DSC_RC_RANGE_PARAM5 (0x0060) +#define DSC_RC_RANGE_PARAM6 (0x0064) +#define DSC_RC_RANGE_PARAM7 (0x0068) +#define DSC_ADJUSTMENT_BITS (0x006C) +#define DSC_BITS_PER_GRP (0x0070) +#define DSC_MULTI_SLICE_CTL (0x0074) +#define DSC_OUT_CTRL (0x0078) +#define DSC_CLK_SEL (0x007C) +#define DSC_CLK_EN (0x0080) +#define DSC_MEM_CTRL (0x0084) +#define DSC_ST_DATAIN (0x0088) +#define DSC_ST_DATAOUT (0x008C) +#define DSC0_ST_SLC_POS (0x0090) +#define DSC1_ST_SLC_POS (0x0094) +#define DSC0_ST_PIC_POS (0x0098) +#define DSC1_ST_PIC_POS (0x009C) +#define DSC0_ST_FIFO (0x00A0) +#define DSC1_ST_FIFO (0x00A4) +#define DSC0_ST_LINEBUF (0x00A8) +#define DSC1_ST_LINEBUF (0x00AC) +#define DSC_ST_ITFC (0x00B0) +#define DSC_RD_SHADOW_SEL (0x00B4) +#define DSC_REG_DEFAULT (0x00B8) + +/******************************************************************************* + ** LDI + */ +#define LDI_DPI0_HRZ_CTRL0 (0x0000) +#define LDI_DPI0_HRZ_CTRL1 (0x0004) +#define LDI_DPI0_HRZ_CTRL2 (0x0008) +#define LDI_VRT_CTRL0 (0x000C) +#define LDI_VRT_CTRL1 (0x0010) +#define LDI_VRT_CTRL2 (0x0014) +#define LDI_PLR_CTRL (0x0018) +#define LDI_SH_MASK_INT (0x001C) +#define LDI_3D_CTRL (0x0020) +#define LDI_CTRL (0x0024) +#define LDI_WORK_MODE (0x0028) +#define LDI_DE_SPACE_LOW (0x002C) +#define LDI_DSI_CMD_MOD_CTRL (0x0030) +#define LDI_DSI_TE_CTRL (0x0034) +#define LDI_DSI_TE_HS_NUM (0x0038) +#define LDI_DSI_TE_HS_WD (0x003C) +#define LDI_DSI_TE_VS_WD (0x0040) +#define LDI_FRM_MSK (0x0044) +#define LDI_FRM_MSK_UP (0x0048) +#define LDI_VINACT_MSK_LEN (0x0050) +#define LDI_VSTATE (0x0054) +#define LDI_DPI0_HSTATE (0x0058) +#define LDI_DPI1_HSTATE (0x005C) +#define LDI_CMD_EVENT_SEL (0x0060) +#define LDI_SRAM_LP_CTRL (0x0064) +#define LDI_ITF_RD_SHADOW (0x006C) +#define LDI_DPI1_HRZ_CTRL0 (0x00F0) +#define LDI_DPI1_HRZ_CTRL1 (0x00F4) +#define LDI_DPI1_HRZ_CTRL2 (0x00F8) +#define LDI_OVERLAP_SIZE (0x00FC) +#define LDI_MEM_CTRL (0x0100) +#define LDI_PM_CTRL (0x0104) +#define LDI_CLK_SEL (0x0108) +#define LDI_CLK_EN (0x010C) +#define LDI_IF_BYPASS (0x0110) +#define LDI_FRM_VALID_DBG (0x0118) +/* LDI GLB*/ +#define LDI_PXL0_DIV2_GT_EN (0x0210) +#define LDI_PXL0_DIV4_GT_EN (0x0214) +#define LDI_PXL0_GT_EN (0x0218) +#define LDI_PXL0_DSI_GT_EN (0x021C) +#define LDI_PXL0_DIVXCFG (0x0220) +#define LDI_DSI1_CLK_SEL (0x0224) +#define LDI_VESA_CLK_SEL (0x0228) +/* DSI1 RST*/ +#define LDI_DSI1_RST_SEL (0x0238) +/* LDI INTERRUPT*/ +#define LDI_MCU_ITF_INTS (0x0240) +#define LDI_MCU_ITF_INT_MSK (0x0244) +#define LDI_CPU_ITF_INTS (0x0248) +#define LDI_CPU_ITF_INT_MSK (0x024C) +/* LDI MODULE CLOCK GATING*/ +#define LDI_MODULE_CLK_SEL (0x0258) +#define LDI_MODULE_CLK_EN (0x025C) + +/******************************************************************************* + ** MIPI DSI + */ +#define MIPIDSI_VERSION_OFFSET (0x0000) +#define MIPIDSI_PWR_UP_OFFSET (0x0004) +#define MIPIDSI_CLKMGR_CFG_OFFSET (0x0008) +#define MIPIDSI_DPI_VCID_OFFSET (0x000c) +#define MIPIDSI_DPI_COLOR_CODING_OFFSET (0x0010) +#define MIPIDSI_DPI_CFG_POL_OFFSET (0x0014) +#define MIPIDSI_DPI_LP_CMD_TIM_OFFSET (0x0018) +#define MIPIDSI_PCKHDL_CFG_OFFSET (0x002c) +#define MIPIDSI_GEN_VCID_OFFSET (0x0030) +#define MIPIDSI_MODE_CFG_OFFSET (0x0034) +#define MIPIDSI_VID_MODE_CFG_OFFSET (0x0038) +#define MIPIDSI_VID_PKT_SIZE_OFFSET (0x003c) +#define MIPIDSI_VID_NUM_CHUNKS_OFFSET (0x0040) +#define MIPIDSI_VID_NULL_SIZE_OFFSET (0x0044) +#define MIPIDSI_VID_HSA_TIME_OFFSET (0x0048) +#define MIPIDSI_VID_HBP_TIME_OFFSET (0x004c) +#define MIPIDSI_VID_HLINE_TIME_OFFSET (0x0050) +#define MIPIDSI_VID_VSA_LINES_OFFSET (0x0054) +#define MIPIDSI_VID_VBP_LINES_OFFSET (0x0058) +#define MIPIDSI_VID_VFP_LINES_OFFSET (0x005c) +#define MIPIDSI_VID_VACTIVE_LINES_OFFSET (0x0060) +#define MIPIDSI_EDPI_CMD_SIZE_OFFSET (0x0064) +#define MIPIDSI_CMD_MODE_CFG_OFFSET (0x0068) +#define MIPIDSI_GEN_HDR_OFFSET (0x006c) +#define MIPIDSI_GEN_PLD_DATA_OFFSET (0x0070) +#define MIPIDSI_CMD_PKT_STATUS_OFFSET (0x0074) +#define MIPIDSI_TO_CNT_CFG_OFFSET (0x0078) +#define MIPIDSI_HS_RD_TO_CNT_OFFSET (0x007C) +#define MIPIDSI_LP_RD_TO_CNT_OFFSET (0x0080) +#define MIPIDSI_HS_WR_TO_CNT_OFFSET (0x0084) +#define MIPIDSI_LP_WR_TO_CNT_OFFSET (0x0088) +#define MIPIDSI_BTA_TO_CNT_OFFSET (0x008C) +#define MIPIDSI_SDF_3D_OFFSET (0x0090) +#define MIPIDSI_LPCLK_CTRL_OFFSET (0x0094) +#define MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET (0x0098) +#define MIPIDSI_PHY_TMR_CFG_OFFSET (0x009c) +#define MIPIDSI_PHY_RSTZ_OFFSET (0x00a0) +#define MIPIDSI_PHY_IF_CFG_OFFSET (0x00a4) +#define MIPIDSI_PHY_ULPS_CTRL_OFFSET (0x00a8) +#define MIPIDSI_PHY_TX_TRIGGERS_OFFSET (0x00ac) +#define MIPIDSI_PHY_STATUS_OFFSET (0x00b0) +#define MIPIDSI_PHY_TST_CTRL0_OFFSET (0x00b4) +#define MIPIDSI_PHY_TST_CTRL1_OFFSET (0x00b8) +#define MIPIDSI_INT_ST0_OFFSET (0x00bc) +#define MIPIDSI_INT_ST1_OFFSET (0x00c0) +#define MIPIDSI_INT_MSK0_OFFSET (0x00c4) +#define MIPIDSI_INT_MSK1_OFFSET (0x00c8) +#define INT_FORCE0 (0x00D8) +#define INT_FORCE1 (0x00DC) +#define MIPIDSI_DSC_PARAMETER_OFFSET (0x00f0) +#define MIPIDSI_PHY_TMR_RD_CFG_OFFSET (0x00f4) +#define VID_SHADOW_CTRL (0x0100) +#define DPI_VCID_ACT (0x010C) +#define DPI_COLOR_CODING_ACT (0x0110) +#define DPI_LP_CMD_TIM_ACT (0x0118) +#define VID_MODE_CFG_ACT (0x0138) +#define VID_PKT_SIZE_ACT (0x013C) +#define VID_NUM_CHUNKS_ACT (0x0140) +#define VID_NULL_SIZE_ACT (0x0144) +#define VID_HSA_TIME_ACT (0x0148) +#define VID_HBP_TIME_ACT (0x014C) +#define VID_HLINE_TIME_ACT (0x0150) +#define VID_VSA_LINES_ACT (0x0154) +#define VID_VBP_LINES_ACT (0x0158) +#define VID_VFP_LINES_ACT (0x015C) +#define VID_VACTIVE_LINES_ACT (0x0160) +#define SDF_3D_ACT (0x0190) + +/******************************************************************************* + ** MMBUF + */ +#define SMC_LOCK (0x0000) +#define SMC_MEM_LP (0x0004) +#define SMC_GCLK_CS (0x000C) +#define SMC_QOS_BACKDOOR (0x0010) +#define SMC_DFX_WCMD_CNT_1ST (0x0014) +#define SMC_DFX_WCMD_CNT_2ND (0x0018) +#define SMC_DFX_WCMD_CNT_3RD (0x001C) +#define SMC_DFX_WCMD_CNT_4TH (0x0020) +#define SMC_DFX_RCMD_CNT_1ST (0x0024) +#define SMC_DFX_RCMD_CNT_2ND (0x0028) +#define SMC_DFX_RCMD_CNT_3RD (0x002C) +#define SMC_DFX_RCMD_CNT_4TH (0x0030) +#define SMC_CS_IDLE (0x0034) +#define SMC_DFX_BFIFO_CNT0 (0x0038) +#define SMC_DFX_RDFIFO_CNT1 (0x003C) +#define SMC_SP_SRAM_STATE0 (0x0040) +#define SMC_SP_SRAM_STATE1 (0x0044) + +enum hisi_fb_pixel_format { + HISI_FB_PIXEL_FORMAT_RGB_565 = 0, + HISI_FB_PIXEL_FORMAT_RGBX_4444, + HISI_FB_PIXEL_FORMAT_RGBA_4444, + HISI_FB_PIXEL_FORMAT_RGBX_5551, + HISI_FB_PIXEL_FORMAT_RGBA_5551, + HISI_FB_PIXEL_FORMAT_RGBX_8888, + HISI_FB_PIXEL_FORMAT_RGBA_8888, + + HISI_FB_PIXEL_FORMAT_BGR_565, + HISI_FB_PIXEL_FORMAT_BGRX_4444, + HISI_FB_PIXEL_FORMAT_BGRA_4444, + HISI_FB_PIXEL_FORMAT_BGRX_5551, + HISI_FB_PIXEL_FORMAT_BGRA_5551, + HISI_FB_PIXEL_FORMAT_BGRX_8888, + HISI_FB_PIXEL_FORMAT_BGRA_8888, + + HISI_FB_PIXEL_FORMAT_YUV_422_I, + + /* YUV Semi-planar */ + HISI_FB_PIXEL_FORMAT_YCbCr_422_SP, /* NV16 */ + HISI_FB_PIXEL_FORMAT_YCrCb_422_SP, + HISI_FB_PIXEL_FORMAT_YCbCr_420_SP, + HISI_FB_PIXEL_FORMAT_YCrCb_420_SP, /* NV21 */ + + /* YUV Planar */ + HISI_FB_PIXEL_FORMAT_YCbCr_422_P, + HISI_FB_PIXEL_FORMAT_YCrCb_422_P, + HISI_FB_PIXEL_FORMAT_YCbCr_420_P, + HISI_FB_PIXEL_FORMAT_YCrCb_420_P, /* HISI_FB_PIXEL_FORMAT_YV12 */ + + /* YUV Package */ + HISI_FB_PIXEL_FORMAT_YUYV_422_Pkg, + HISI_FB_PIXEL_FORMAT_UYVY_422_Pkg, + HISI_FB_PIXEL_FORMAT_YVYU_422_Pkg, + HISI_FB_PIXEL_FORMAT_VYUY_422_Pkg, + HISI_FB_PIXEL_FORMAT_MAX, + + HISI_FB_PIXEL_FORMAT_UNSUPPORT = 800 +}; + +struct dss_hw_ctx { + void __iomem *base; + struct regmap *noc_regmap; + struct reset_control *reset; + + void __iomem *noc_dss_base; + void __iomem *peri_crg_base; + void __iomem *pmc_base; + void __iomem *sctrl_base; + + struct clk *dss_axi_clk; + struct clk *dss_pclk_dss_clk; + struct clk *dss_pri_clk; + struct clk *dss_pxl0_clk; + struct clk *dss_pxl1_clk; + struct clk *dss_mmbuf_clk; + struct clk *dss_pclk_mmbuf_clk; + + bool power_on; + int irq; + + wait_queue_head_t vactive0_start_wq; + u32 vactive0_start_flag; + ktime_t vsync_timestamp; + ktime_t vsync_timestamp_prev; + + struct iommu_domain *mmu_domain; + struct ion_client *ion_client; + struct ion_handle *ion_handle; + struct iommu_map_format iommu_format; + char __iomem *screen_base; + unsigned long smem_start; + unsigned long screen_size; +}; + +struct dss_crtc { + struct drm_crtc base; + struct dss_hw_ctx *ctx; + bool enable; + u32 out_format; + u32 bgr_fmt; +}; + +struct dss_plane { + struct drm_plane base; + /*void *ctx;*/ + void *acrtc; + u8 ch; /* channel */ +}; + +struct dss_data { + struct dss_crtc acrtc; + struct dss_plane aplane[DSS_CH_NUM]; + struct dss_hw_ctx ctx; +}; + +/* ade-format info: */ +struct dss_format { + u32 pixel_format; + enum hisi_fb_pixel_format dss_format; +}; + +#define MIPI_DPHY_NUM (2) + +/* IFBC compress mode */ +enum IFBC_TYPE { + IFBC_TYPE_NONE = 0, + IFBC_TYPE_ORISE2X, + IFBC_TYPE_ORISE3X, + IFBC_TYPE_HIMAX2X, + IFBC_TYPE_RSP2X, + IFBC_TYPE_RSP3X, + IFBC_TYPE_VESA2X_SINGLE, + IFBC_TYPE_VESA3X_SINGLE, + IFBC_TYPE_VESA2X_DUAL, + IFBC_TYPE_VESA3X_DUAL, + IFBC_TYPE_VESA3_75X_DUAL, + + IFBC_TYPE_MAX +}; + +/* IFBC compress mode */ +enum IFBC_COMP_MODE { + IFBC_COMP_MODE_0 = 0, + IFBC_COMP_MODE_1, + IFBC_COMP_MODE_2, + IFBC_COMP_MODE_3, + IFBC_COMP_MODE_4, + IFBC_COMP_MODE_5, + IFBC_COMP_MODE_6, +}; + +/* xres_div */ +enum XRES_DIV { + XRES_DIV_1 = 1, + XRES_DIV_2, + XRES_DIV_3, + XRES_DIV_4, + XRES_DIV_5, + XRES_DIV_6, +}; + +/* yres_div */ +enum YRES_DIV { + YRES_DIV_1 = 1, + YRES_DIV_2, + YRES_DIV_3, + YRES_DIV_4, + YRES_DIV_5, + YRES_DIV_6, +}; + +/* pxl0_divxcfg */ +enum PXL0_DIVCFG { + PXL0_DIVCFG_0 = 0, + PXL0_DIVCFG_1, + PXL0_DIVCFG_2, + PXL0_DIVCFG_3, + PXL0_DIVCFG_4, + PXL0_DIVCFG_5, + PXL0_DIVCFG_6, + PXL0_DIVCFG_7, +}; + +/* pxl0_div2_gt_en */ +enum PXL0_DIV2_GT_EN { + PXL0_DIV2_GT_EN_CLOSE = 0, + PXL0_DIV2_GT_EN_OPEN, +}; + +/* pxl0_div4_gt_en */ +enum PXL0_DIV4_GT_EN { + PXL0_DIV4_GT_EN_CLOSE = 0, + PXL0_DIV4_GT_EN_OPEN, +}; + +/* pxl0_dsi_gt_en */ +enum PXL0_DSI_GT_EN { + PXL0_DSI_GT_EN_0 = 0, + PXL0_DSI_GT_EN_1, + PXL0_DSI_GT_EN_2, + PXL0_DSI_GT_EN_3, +}; + +typedef struct mipi_ifbc_division { + u32 xres_div; + u32 yres_div; + u32 comp_mode; + u32 pxl0_div2_gt_en; + u32 pxl0_div4_gt_en; + u32 pxl0_divxcfg; + u32 pxl0_dsi_gt_en; +} mipi_ifbc_division_t; + +/******************************************************************************* +** +*/ +#define outp32(addr, val) writel(val, addr) +#define outp16(addr, val) writew(val, addr) +#define outp8(addr, val) writeb(val, addr) +#define outp(addr, val) outp32(addr, val) + +#define inp32(addr) readl(addr) +#define inp16(addr) readw(addr) +#define inp8(addr) readb(addr) +#define inp(addr) inp32(addr) + +#define inpw(port) readw(port) +#define outpw(port, val) writew(val, port) +#define inpdw(port) readl(port) +#define outpdw(port, val) writel(val, port) + +#ifndef ALIGN_DOWN +#define ALIGN_DOWN(val, al) ((val) & ~((al) - 1)) +#endif +#ifndef ALIGN_UP +#define ALIGN_UP(val, al) (((val) + ((al) - 1)) & ~((al) - 1)) +#endif + +#define to_dss_crtc(crtc) \ + container_of(crtc, struct dss_crtc, base) + +#define to_dss_plane(plane) \ + container_of(plane, struct dss_plane, base) + +#endif diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.c b/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.c new file mode 100644 index 000000000000..2d6809b72b42 --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.c @@ -0,0 +1,731 @@ +/* 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 "drm_mipi_dsi.h" +#include "kirin_drm_dpe_utils.h" + +int g_debug_set_reg_val = 0; + +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] = { + /*single mipi*/ + { + /*none*/ + {XRES_DIV_1, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_CLOSE, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_0, PXL0_DSI_GT_EN_1}, + /*orise2x*/ + {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_OPEN, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}, + /*orise3x*/ + {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_1, PXL0_DIV2_GT_EN_OPEN, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}, + /*himax2x*/ + {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_2, PXL0_DIV2_GT_EN_OPEN, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}, + /*rsp2x*/ + {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_3, PXL0_DIV2_GT_EN_CLOSE, + PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}, + /*rsp3x [NOTE]reality: xres_div = 1.5, yres_div = 2, amended in "mipi_ifbc_get_rect" function*/ + {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_4, PXL0_DIV2_GT_EN_CLOSE, + PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}, + /*vesa2x_1pipe*/ + {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}, + /*vesa3x_1pipe*/ + {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}, + /*vesa2x_2pipe*/ + {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}, + /*vesa3x_2pipe*/ + {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3} + }, + + /*dual mipi*/ + { + /*none*/ + {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_CLOSE, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}, + /*orise2x*/ + {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_OPEN, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}, + /*orise3x*/ + {XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_1, PXL0_DIV2_GT_EN_OPEN, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, PXL0_DSI_GT_EN_3}, + /*himax2x*/ + {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_2, PXL0_DIV2_GT_EN_OPEN, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}, + /*rsp2x*/ + {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_3, PXL0_DIV2_GT_EN_CLOSE, + PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}, + /*rsp3x*/ + {XRES_DIV_3, YRES_DIV_2, IFBC_COMP_MODE_4, PXL0_DIV2_GT_EN_CLOSE, + PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_5, PXL0_DSI_GT_EN_3}, + /*vesa2x_1pipe*/ + {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}, + /*vesa3x_1pipe*/ + {XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, PXL0_DSI_GT_EN_3}, + /*vesa2x_2pipe*/ + {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}, + /*vesa3x_2pipe*/ + {XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN, + PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, 3} } +}; + +void set_reg(char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs) +{ + u32 mask = (1UL << bw) - 1UL; + u32 tmp = 0; + + tmp = inp32(addr); + tmp &= ~(mask << bs); + + outp32(addr, tmp | ((val & mask) << bs)); + + if (g_debug_set_reg_val) { + printk(KERN_INFO "writel: [%p] = 0x%x\n", addr, + tmp | ((val & mask) << bs)); + } +} + +static int mipi_ifbc_get_rect(struct dss_rect *rect) +{ + u32 ifbc_type; + u32 mipi_idx; + u32 xres_div; + u32 yres_div; + + ifbc_type = IFBC_TYPE_NONE; + mipi_idx = 0; + + xres_div = g_mipi_ifbc_division[mipi_idx][ifbc_type].xres_div; + yres_div = g_mipi_ifbc_division[mipi_idx][ifbc_type].yres_div; + + if ((rect->w % xres_div) > 0) + DRM_ERROR("xres(%d) is not division_h(%d) pixel aligned!\n", rect->w, xres_div); + + if ((rect->h % yres_div) > 0) + DRM_ERROR("yres(%d) is not division_v(%d) pixel aligned!\n", rect->h, yres_div); + + /* + ** [NOTE] rsp3x && single_mipi CMD mode amended xres_div = 1.5, yres_div = 2 , + ** VIDEO mode amended xres_div = 3, yres_div = 1 + */ + rect->w /= xres_div; + rect->h /= yres_div; + + return 0; +} + +static void init_ldi_pxl_div(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + char __iomem *ldi_base; + struct drm_display_mode *mode; + struct drm_display_mode *adj_mode; + + u32 ifbc_type = 0; + u32 mipi_idx = 0; + u32 pxl0_div2_gt_en = 0; + u32 pxl0_div4_gt_en = 0; + u32 pxl0_divxcfg = 0; + u32 pxl0_dsi_gt_en = 0; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + mode = &acrtc->base.state->mode; + adj_mode = &acrtc->base.state->adjusted_mode; + + ldi_base = ctx->base + DSS_LDI0_OFFSET; + + ifbc_type = IFBC_TYPE_NONE; + mipi_idx = 0; + + pxl0_div2_gt_en = g_mipi_ifbc_division[mipi_idx][ifbc_type].pxl0_div2_gt_en; + pxl0_div4_gt_en = g_mipi_ifbc_division[mipi_idx][ifbc_type].pxl0_div4_gt_en; + pxl0_divxcfg = g_mipi_ifbc_division[mipi_idx][ifbc_type].pxl0_divxcfg; + pxl0_dsi_gt_en = g_mipi_ifbc_division[mipi_idx][ifbc_type].pxl0_dsi_gt_en; + + set_reg(ldi_base + LDI_PXL0_DIV2_GT_EN, pxl0_div2_gt_en, 1, 0); + set_reg(ldi_base + LDI_PXL0_DIV4_GT_EN, pxl0_div4_gt_en, 1, 0); + set_reg(ldi_base + LDI_PXL0_GT_EN, 0x1, 1, 0); + set_reg(ldi_base + LDI_PXL0_DSI_GT_EN, pxl0_dsi_gt_en, 2, 0); + set_reg(ldi_base + LDI_PXL0_DIVXCFG, pxl0_divxcfg, 3, 0); +} + +void init_other(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + char __iomem *dss_base; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + dss_base = ctx->base; + + /** + * VESA_CLK_SEL is set to 0 for initial, + * 1 is needed only by vesa dual pipe compress + */ + set_reg(dss_base + DSS_LDI0_OFFSET + LDI_VESA_CLK_SEL, 0, 1, 0); +} + +void init_ldi(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + char __iomem *ldi_base; + struct drm_display_mode *mode; + struct drm_display_mode *adj_mode; + + dss_rect_t rect = {0, 0, 0, 0}; + u32 hfp, hbp, hsw, vfp, vbp, vsw; + u32 vsync_plr = 0; + u32 hsync_plr = 0; + u32 pixelclk_plr = 0; + u32 data_en_plr = 0; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return ; + } + + mode = &acrtc->base.state->mode; + adj_mode = &acrtc->base.state->adjusted_mode; + + hfp = mode->hsync_start - mode->hdisplay; + hbp = mode->htotal - mode->hsync_end; + hsw = mode->hsync_end - mode->hsync_start; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + vsw = mode->vsync_end - mode->vsync_start; + + ldi_base = ctx->base + DSS_LDI0_OFFSET; + + rect.x = 0; + rect.y = 0; + rect.w = mode->hdisplay; + rect.h = mode->vdisplay; + mipi_ifbc_get_rect(&rect); + + init_ldi_pxl_div(acrtc); + + outp32(ldi_base + LDI_DPI0_HRZ_CTRL0, + hfp | ((hbp + DSS_WIDTH(hsw)) << 16)); + outp32(ldi_base + LDI_DPI0_HRZ_CTRL1, 0); + outp32(ldi_base + LDI_DPI0_HRZ_CTRL2, DSS_WIDTH(rect.w)); + outp32(ldi_base + LDI_VRT_CTRL0, + vfp | (vbp << 16)); + outp32(ldi_base + LDI_VRT_CTRL1, DSS_HEIGHT(vsw)); + outp32(ldi_base + LDI_VRT_CTRL2, DSS_HEIGHT(rect.h)); + + outp32(ldi_base + LDI_PLR_CTRL, + vsync_plr | (hsync_plr << 1) | + (pixelclk_plr << 2) | (data_en_plr << 3)); + + /* bpp*/ + set_reg(ldi_base + LDI_CTRL, acrtc->out_format, 2, 3); + /* bgr*/ + set_reg(ldi_base + LDI_CTRL, acrtc->bgr_fmt, 1, 13); + + /* for ddr pmqos*/ + outp32(ldi_base + LDI_VINACT_MSK_LEN, vfp); + + /*cmd event sel*/ + outp32(ldi_base + LDI_CMD_EVENT_SEL, 0x1); + + /* for 1Hz LCD and mipi command LCD*/ + set_reg(ldi_base + LDI_DSI_CMD_MOD_CTRL, 0x1, 1, 1); + + /*ldi_data_gate(hisifd, true);*/ + +#ifdef CONFIG_HISI_FB_LDI_COLORBAR_USED + /* colorbar width*/ + set_reg(ldi_base + LDI_CTRL, DSS_WIDTH(0x3c), 7, 6); + /* colorbar ort*/ + set_reg(ldi_base + LDI_WORK_MODE, 0x0, 1, 1); + /* colorbar enable*/ + set_reg(ldi_base + LDI_WORK_MODE, 0x0, 1, 0); +#else + /* normal*/ + set_reg(ldi_base + LDI_WORK_MODE, 0x1, 1, 0); +#endif + + /* ldi disable*/ + set_reg(ldi_base + LDI_CTRL, 0x0, 1, 0); +} + +void init_dbuf(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + struct drm_display_mode *mode; + struct drm_display_mode *adj_mode; + char __iomem *dbuf_base; + + int sram_valid_num = 0; + int sram_max_mem_depth = 0; + int sram_min_support_depth = 0; + + u32 thd_rqos_in = 0; + u32 thd_rqos_out = 0; + u32 thd_wqos_in = 0; + u32 thd_wqos_out = 0; + u32 thd_cg_in = 0; + u32 thd_cg_out = 0; + u32 thd_wr_wait = 0; + u32 thd_cg_hold = 0; + u32 thd_flux_req_befdfs_in = 0; + u32 thd_flux_req_befdfs_out = 0; + u32 thd_flux_req_aftdfs_in = 0; + u32 thd_flux_req_aftdfs_out = 0; + u32 thd_dfs_ok = 0; + u32 dfs_ok_mask = 0; + u32 thd_flux_req_sw_en = 1; + u32 hfp, hbp, hsw, vfp, vbp, vsw; + + int dfs_time = 0; + int dfs_time_min = 0; + int depth = 0; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + mode = &acrtc->base.state->mode; + adj_mode = &acrtc->base.state->adjusted_mode; + + hfp = mode->hsync_start - mode->hdisplay; + hbp = mode->htotal - mode->hsync_end; + hsw = mode->hsync_end - mode->hsync_start; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + vsw = mode->vsync_end - mode->vsync_start; + + dbuf_base = ctx->base + DSS_DBUF0_OFFSET; + + if (mode->hdisplay * mode->vdisplay >= RES_4K_PHONE) + dfs_time_min = DFS_TIME_MIN_4K; + else + dfs_time_min = DFS_TIME_MIN; + + dfs_time = DFS_TIME; + depth = DBUF0_DEPTH; + + DRM_DEBUG("dfs_time=%d,\n" + "adj_mode->clock=%d\n" + "hsw=%d\n" + "hbp=%d\n" + "hfp=%d\n" + "mode->hdisplay=%d\n" + "mode->vdisplay=%d\n", + dfs_time, + adj_mode->clock, + hsw, + hbp, + hfp, + mode->hdisplay, + mode->vdisplay); + + /* + ** int K = 0; + ** int Tp = 1000000 / adj_mode->clock; + ** K = (hsw + hbp + mode->hdisplay + + ** hfp) / mode->hdisplay; + ** thd_cg_out = dfs_time / (Tp * K * 6); + */ + thd_cg_out = (dfs_time * adj_mode->clock * 1000UL * mode->hdisplay) / + (((hsw + hbp + hfp) + mode->hdisplay) * 6 * 1000000UL); + + sram_valid_num = thd_cg_out / depth; + thd_cg_in = (sram_valid_num + 1) * depth - 1; + + sram_max_mem_depth = (sram_valid_num + 1) * depth; + + thd_rqos_in = thd_cg_out * 85 / 100; + thd_rqos_out = thd_cg_out; + thd_flux_req_befdfs_in = GET_FLUX_REQ_IN(sram_max_mem_depth); + thd_flux_req_befdfs_out = GET_FLUX_REQ_OUT(sram_max_mem_depth); + + sram_min_support_depth = dfs_time_min * mode->hdisplay / (1000000 / 60 / (mode->vdisplay + + vbp + vfp + vsw) * (DBUF_WIDTH_BIT / 3 / BITS_PER_BYTE)); + + /*thd_flux_req_aftdfs_in =[(sram_valid_num+1)*depth - 50*HSIZE/((1000000/60/(VSIZE+VFP+VBP+VSW))*6)]/3*/ + thd_flux_req_aftdfs_in = (sram_max_mem_depth - sram_min_support_depth) / 3; + /*thd_flux_req_aftdfs_out = 2*[(sram_valid_num+1)* depth - 50*HSIZE/((1000000/60/(VSIZE+VFP+VBP+VSW))*6)]/3*/ + thd_flux_req_aftdfs_out = 2 * (sram_max_mem_depth - sram_min_support_depth) / 3; + + thd_dfs_ok = thd_flux_req_befdfs_in; + + DRM_DEBUG("hdisplay=%d\n" + "vdisplay=%d\n" + "sram_valid_num=%d,\n" + "thd_rqos_in=0x%x\n" + "thd_rqos_out=0x%x\n" + "thd_cg_in=0x%x\n" + "thd_cg_out=0x%x\n" + "thd_flux_req_befdfs_in=0x%x\n" + "thd_flux_req_befdfs_out=0x%x\n" + "thd_flux_req_aftdfs_in=0x%x\n" + "thd_flux_req_aftdfs_out=0x%x\n" + "thd_dfs_ok=0x%x\n", + mode->hdisplay, + mode->vdisplay, + sram_valid_num, + thd_rqos_in, + thd_rqos_out, + thd_cg_in, + thd_cg_out, + thd_flux_req_befdfs_in, + thd_flux_req_befdfs_out, + thd_flux_req_aftdfs_in, + thd_flux_req_aftdfs_out, + thd_dfs_ok); + + outp32(dbuf_base + DBUF_FRM_SIZE, mode->hdisplay * mode->vdisplay); + outp32(dbuf_base + DBUF_FRM_HSIZE, DSS_WIDTH(mode->hdisplay)); + outp32(dbuf_base + DBUF_SRAM_VALID_NUM, sram_valid_num); + + outp32(dbuf_base + DBUF_THD_RQOS, (thd_rqos_out << 16) | thd_rqos_in); + outp32(dbuf_base + DBUF_THD_WQOS, (thd_wqos_out << 16) | thd_wqos_in); + outp32(dbuf_base + DBUF_THD_CG, (thd_cg_out << 16) | thd_cg_in); + outp32(dbuf_base + DBUF_THD_OTHER, (thd_cg_hold << 16) | thd_wr_wait); + outp32(dbuf_base + DBUF_THD_FLUX_REQ_BEF, (thd_flux_req_befdfs_out << 16) | thd_flux_req_befdfs_in); + outp32(dbuf_base + DBUF_THD_FLUX_REQ_AFT, (thd_flux_req_aftdfs_out << 16) | thd_flux_req_aftdfs_in); + outp32(dbuf_base + DBUF_THD_DFS_OK, thd_dfs_ok); + outp32(dbuf_base + DBUF_FLUX_REQ_CTRL, (dfs_ok_mask << 1) | thd_flux_req_sw_en); + + outp32(dbuf_base + DBUF_DFS_LP_CTRL, 0x1); +} + +void init_dpp(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + struct drm_display_mode *mode; + struct drm_display_mode *adj_mode; + char __iomem *dpp_base; + char __iomem *mctl_sys_base; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + mode = &acrtc->base.state->mode; + adj_mode = &acrtc->base.state->adjusted_mode; + + dpp_base = ctx->base + DSS_DPP_OFFSET; + mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET; + + outp32(dpp_base + DPP_IMG_SIZE_BEF_SR, + (DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay)); + outp32(dpp_base + DPP_IMG_SIZE_AFT_SR, + (DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay)); + +#ifdef CONFIG_HISI_FB_DPP_COLORBAR_USED + void __iomem *mctl_base; + 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); + + mctl_base = ctx->base + + g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE]; + + set_reg(mctl_base + MCTL_CTL_MUTEX, 0x1, 1, 0); + set_reg(mctl_base + MCTL_CTL_EN, 0x1, 32, 0); + set_reg(mctl_base + MCTL_CTL_TOP, 0x2, 32, 0); /*auto mode*/ + set_reg(mctl_base + MCTL_CTL_DBG, 0xB13A00, 32, 0); + + 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 +} + +void enable_ldi(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + char __iomem *ldi_base; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + ldi_base = ctx->base + DSS_LDI0_OFFSET; + + /* ldi enable */ + set_reg(ldi_base + LDI_CTRL, 0x1, 1, 0); +} + +void disable_ldi(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + char __iomem *ldi_base; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + ldi_base = ctx->base + DSS_LDI0_OFFSET; + + /* ldi disable */ + set_reg(ldi_base + LDI_CTRL, 0x0, 1, 0); +} + +void dpe_interrupt_clear(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + char __iomem *dss_base; + u32 clear; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + dss_base = ctx->base; + + clear = ~0; + outp32(dss_base + GLB_CPU_PDP_INTS, clear); + outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS, clear); + outp32(dss_base + DSS_DPP_OFFSET + DPP_INTS, clear); + + outp32(dss_base + DSS_DBG_OFFSET + DBG_MCTL_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_WCH0_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_WCH1_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH0_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH1_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH2_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH3_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH4_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH5_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH6_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH7_INTS, clear); + outp32(dss_base + DSS_DBG_OFFSET + DBG_DSS_GLB_INTS, clear); +} + +void dpe_interrupt_unmask(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + char __iomem *dss_base; + u32 unmask; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + dss_base = ctx->base; + + unmask = ~0; + unmask &= ~(BIT_DPP_INTS | BIT_ITF0_INTS | BIT_MMU_IRPT_NS); + outp32(dss_base + GLB_CPU_PDP_INT_MSK, unmask); + + unmask = ~0; + unmask &= ~(BIT_VSYNC | BIT_VACTIVE0_START + | BIT_VACTIVE0_END | BIT_FRM_END | BIT_LDI_UNFLOW); + + outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, unmask); +} + +void dpe_interrupt_mask(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + char __iomem *dss_base; + u32 mask; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return ; + } + + dss_base = ctx->base; + + mask = ~0; + outp32(dss_base + GLB_CPU_PDP_INT_MSK, mask); + outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, mask); + outp32(dss_base + DSS_DPP_OFFSET + DPP_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_DSS_GLB_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_MCTL_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_WCH0_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_WCH1_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH0_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH1_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH2_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH3_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH4_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH5_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH6_INT_MSK, mask); + outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH7_INT_MSK, mask); +} + +int dpe_init(struct dss_crtc *acrtc) +{ + struct drm_display_mode *mode; + struct drm_display_mode *adj_mode; + + mode = &acrtc->base.state->mode; + adj_mode = &acrtc->base.state->adjusted_mode; + + init_dbuf(acrtc); + init_dpp(acrtc); + init_other(acrtc); + init_ldi(acrtc); + + hisifb_dss_on(acrtc->ctx); + hisi_dss_mctl_on(acrtc->ctx); + + hisi_dss_mctl_mutex_lock(acrtc->ctx); + + hisi_dss_ovl_base_config(acrtc->ctx, mode->hdisplay, mode->vdisplay); + + hisi_dss_mctl_mutex_unlock(acrtc->ctx); + + enable_ldi(acrtc); + + mdelay(60); + + return 0; +} + +void dss_inner_clk_pdp_enable(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + char __iomem *dss_base; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + dss_base = ctx->base; + + outp32(dss_base + DSS_IFBC_OFFSET + IFBC_MEM_CTRL, 0x00000088); + outp32(dss_base + DSS_DSC_OFFSET + DSC_MEM_CTRL, 0x00000888); + outp32(dss_base + DSS_LDI0_OFFSET + LDI_MEM_CTRL, 0x00000008); + outp32(dss_base + DSS_DBUF0_OFFSET + DBUF_MEM_CTRL, 0x00000008); + outp32(dss_base + DSS_DPP_DITHER_OFFSET + DITHER_MEM_CTRL, 0x00000008); +} + +void dss_inner_clk_common_enable(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + char __iomem *dss_base; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + dss_base = ctx->base; + + /*core/axi/mmbuf*/ + outp32(dss_base + DSS_CMDLIST_OFFSET + CMD_MEM_CTRL, 0x00000008); /*cmd mem*/ + + outp32(dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_v0 ,scf mem*/ + outp32(dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);/*rch_v0 ,scf mem*/ + outp32(dss_base + DSS_RCH_VG0_ARSR_OFFSET + ARSR2P_LB_MEM_CTRL, 0x00000008);/*rch_v0 ,arsr2p mem*/ + outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + VPP_MEM_CTRL, 0x00000008);/*rch_v0 ,vpp mem*/ + outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_v0 ,dma_buf mem*/ + outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_v0 ,afbcd mem*/ + + outp32(dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_v1 ,scf mem*/ + outp32(dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);/*rch_v1 ,scf mem*/ + 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*/ + 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*/ + outp32(dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x0000008);/*rch_g0 ,scf mem*/ + outp32(dss_base + DSS_RCH_G0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_g0 ,dma_buf mem*/ + outp32(dss_base + DSS_RCH_G0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_g0 ,afbcd mem*/ + + outp32(dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_g1 ,scf mem*/ + outp32(dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x0000008);/*rch_g1 ,scf mem*/ + outp32(dss_base + DSS_RCH_G1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_g1 ,dma_buf mem*/ + outp32(dss_base + DSS_RCH_G1_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_g1 ,afbcd mem*/ + + outp32(dss_base + DSS_RCH_D0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d0 ,dma_buf mem*/ + outp32(dss_base + DSS_RCH_D0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_d0 ,afbcd mem*/ + outp32(dss_base + DSS_RCH_D1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d1 ,dma_buf mem*/ + outp32(dss_base + DSS_RCH_D2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d2 ,dma_buf mem*/ + outp32(dss_base + DSS_RCH_D3_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d3 ,dma_buf mem*/ + + outp32(dss_base + DSS_WCH0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*wch0 DMA/AFBCE mem*/ + outp32(dss_base + DSS_WCH0_DMA_OFFSET + AFBCE_MEM_CTRL, 0x00000888);/*wch0 DMA/AFBCE mem*/ + outp32(dss_base + DSS_WCH0_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);/*wch0 rot mem*/ + 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*/ +} +int dpe_irq_enable(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + if (ctx->irq) + enable_irq(ctx->irq); + + return 0; +} + +int dpe_irq_disable(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx; + + ctx = acrtc->ctx; + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + if (ctx->irq) + disable_irq(ctx->irq); + + /*disable_irq_nosync(ctx->irq);*/ + + return 0; +} diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.h b/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.h new file mode 100644 index 000000000000..7ee992273d72 --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.h @@ -0,0 +1,58 @@ +/* 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_DRM_DPE_UTILS_H +#define KIRIN_DRM_DPE_UTILS_H + +#include "kirin_dpe_reg.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); + +void init_dbuf(struct dss_crtc *acrtc); +void init_dpp(struct dss_crtc *acrtc); +void init_other(struct dss_crtc *acrtc); +void init_ldi(struct dss_crtc *acrtc); + +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 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_irq_enable(struct dss_crtc *acrtc); +int dpe_irq_disable(struct dss_crtc *acrtc); + +int dpe_init(struct dss_crtc *acrtc); + +void hisifb_dss_on(struct dss_hw_ctx *ctx); +void hisi_dss_mctl_on(struct dss_hw_ctx *ctx); + +void hisi_dss_unflow_handler(struct dss_hw_ctx *ctx, bool unmask); +int hisi_dss_mctl_mutex_lock(struct dss_hw_ctx *ctx); +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); + +u32 dss_get_format(u32 pixel_format); + +#endif diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_drv.c b/drivers/staging/hikey9xx/gpu/kirin_drm_drv.c new file mode 100644 index 000000000000..edb690062f64 --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/kirin_drm_drv.c @@ -0,0 +1,380 @@ +/* + * Hisilicon Kirin SoCs drm master driver + * + * Copyright (c) 2016 Linaro Limited. + * Copyright (c) 2014-2016 Hisilicon Limited. + * + * Author: + * <cailiwei@xxxxxxxxxxxxx> + * <zhengwanchun@xxxxxxxxxxxxx> + * + * 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. + * + */ + +#include <linux/of_platform.h> +#include <linux/component.h> +#include <linux/of_graph.h> + +#include <drm/drmP.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> + +#include "kirin_drm_drv.h" + + +#ifdef CONFIG_DRM_FBDEV_EMULATION +static bool fbdev = true; +MODULE_PARM_DESC(fbdev, "Enable fbdev compat layer"); +module_param(fbdev, bool, 0600); +#endif + + +static struct kirin_dc_ops *dc_ops; + +static int kirin_drm_kms_cleanup(struct drm_device *dev) +{ + struct kirin_drm_private *priv = dev->dev_private; + + if (priv->fbdev) { + kirin_drm_fbdev_fini(dev); + priv->fbdev = NULL; + } + + drm_kms_helper_poll_fini(dev); + drm_vblank_cleanup(dev); + dc_ops->cleanup(dev); + drm_mode_config_cleanup(dev); + devm_kfree(dev->dev, priv); + dev->dev_private = NULL; + + return 0; +} + +static void kirin_fbdev_output_poll_changed(struct drm_device *dev) +{ + struct kirin_drm_private *priv = dev->dev_private; + + dsi_set_output_client(dev); + + if (priv->fbdev) + drm_fb_helper_hotplug_event(priv->fbdev); + else + priv->fbdev = kirin_drm_fbdev_init(dev); +} + +static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs = { + .fb_create = drm_fb_cma_create, + .output_poll_changed = kirin_fbdev_output_poll_changed, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static void kirin_drm_mode_config_init(struct drm_device *dev) +{ + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + + dev->mode_config.max_width = 2048; + dev->mode_config.max_height = 2048; + + dev->mode_config.funcs = &kirin_drm_mode_config_funcs; +} + +static int kirin_drm_kms_init(struct drm_device *dev) +{ + struct kirin_drm_private *priv; + int ret; + + priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + dev->dev_private = priv; + dev_set_drvdata(dev->dev, dev); + + /* dev->mode_config initialization */ + drm_mode_config_init(dev); + kirin_drm_mode_config_init(dev); + + /* display controller init */ + ret = dc_ops->init(dev); + if (ret) + goto err_mode_config_cleanup; + + /* bind and init sub drivers */ + ret = component_bind_all(dev->dev, dev); + if (ret) { + DRM_ERROR("failed to bind all component.\n"); + goto err_dc_cleanup; + } + + /* vblank init */ + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); + if (ret) { + DRM_ERROR("failed to initialize vblank.\n"); + goto err_unbind_all; + } + /* with irq_enabled = true, we can use the vblank feature. */ + dev->irq_enabled = true; + + /* reset all the states of crtc/plane/encoder/connector */ + drm_mode_config_reset(dev); + + //if (fbdev) + // priv->fbdev = kirin_drm_fbdev_init(dev); + + /* init kms poll for handling hpd */ + drm_kms_helper_poll_init(dev); + + /* force detection after connectors init */ + (void)drm_helper_hpd_irq_event(dev); + + return 0; + +err_unbind_all: + component_unbind_all(dev->dev, dev); +err_dc_cleanup: + dc_ops->cleanup(dev); +err_mode_config_cleanup: + drm_mode_config_cleanup(dev); + devm_kfree(dev->dev, priv); + dev->dev_private = NULL; + + return ret; +} + +static const struct file_operations kirin_drm_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif + .poll = drm_poll, + .read = drm_read, + .llseek = no_llseek, + .mmap = drm_gem_cma_mmap, +}; + +static int kirin_gem_cma_dumb_create(struct drm_file *file, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + return drm_gem_cma_dumb_create_internal(file, dev, args); +} + +static int kirin_drm_connectors_register(struct drm_device *dev) +{ + struct drm_connector *connector; + struct drm_connector *failed_connector; + int ret; + + mutex_lock(&dev->mode_config.mutex); + drm_for_each_connector(connector, dev) { + ret = drm_connector_register(connector); + if (ret) { + failed_connector = connector; + goto err; + } + } + mutex_unlock(&dev->mode_config.mutex); + + return 0; + +err: + drm_for_each_connector(connector, dev) { + if (failed_connector == connector) + break; + drm_connector_unregister(connector); + } + mutex_unlock(&dev->mode_config.mutex); + + return ret; +} + +static struct drm_driver kirin_drm_driver = { + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | + DRIVER_ATOMIC | DRIVER_HAVE_IRQ | DRIVER_RENDER, + .fops = &kirin_drm_fops, + .set_busid = drm_platform_set_busid, + + .gem_free_object = drm_gem_cma_free_object, + .gem_vm_ops = &drm_gem_cma_vm_ops, + .dumb_create = kirin_gem_cma_dumb_create, + .dumb_map_offset = drm_gem_cma_dumb_map_offset, + .dumb_destroy = drm_gem_dumb_destroy, + + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, + .gem_prime_vmap = drm_gem_cma_prime_vmap, + .gem_prime_vunmap = drm_gem_cma_prime_vunmap, + .gem_prime_mmap = drm_gem_cma_prime_mmap, + + .name = "kirin", + .desc = "Hisilicon Kirin SoCs' DRM Driver", + .date = "20170309", + .major = 1, + .minor = 0, +}; + +#ifdef CONFIG_OF +/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx + * (or probably any other).. so probably some room for some helpers + */ +static int compare_of(struct device *dev, void *data) +{ + return dev->of_node == data; +} +#else +static int compare_dev(struct device *dev, void *data) +{ + return dev == data; +} +#endif + +static int kirin_drm_bind(struct device *dev) +{ + struct drm_driver *driver = &kirin_drm_driver; + struct drm_device *drm_dev; + int ret; + + //drm_platform_init(&kirin_drm_driver, to_platform_device(dev)); + + drm_dev = drm_dev_alloc(driver, dev); + if (!drm_dev) + return -ENOMEM; + + drm_dev->platformdev = to_platform_device(dev); + + ret = kirin_drm_kms_init(drm_dev); + if (ret) + goto err_drm_dev_unref; + + ret = drm_dev_register(drm_dev, 0); + if (ret) + goto err_kms_cleanup; + + /* connectors should be registered after drm device register */ + ret = kirin_drm_connectors_register(drm_dev); + if (ret) + goto err_drm_dev_unregister; + + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", + driver->name, driver->major, driver->minor, driver->patchlevel, + driver->date, drm_dev->primary->index); + + return 0; + +err_drm_dev_unregister: + drm_dev_unregister(drm_dev); +err_kms_cleanup: + kirin_drm_kms_cleanup(drm_dev); +err_drm_dev_unref: + drm_dev_unref(drm_dev); + + return ret; +} + +static void kirin_drm_unbind(struct device *dev) +{ + drm_put_dev(dev_get_drvdata(dev)); +} + +static const struct component_master_ops kirin_drm_ops = { + .bind = kirin_drm_bind, + .unbind = kirin_drm_unbind, +}; + +static struct device_node *kirin_get_remote_node(struct device_node *np) +{ + struct device_node *endpoint, *remote; + + /* get the first endpoint, in our case only one remote node + * is connected to display controller. + */ + endpoint = of_graph_get_next_endpoint(np, NULL); + if (!endpoint) { + DRM_ERROR("no valid endpoint node\n"); + return ERR_PTR(-ENODEV); + } + of_node_put(endpoint); + + remote = of_graph_get_remote_port_parent(endpoint); + if (!remote) { + DRM_ERROR("no valid remote node\n"); + return ERR_PTR(-ENODEV); + } + of_node_put(remote); + + if (!of_device_is_available(remote)) { + DRM_ERROR("not available for remote node\n"); + return ERR_PTR(-ENODEV); + } + + return remote; +} + +static int kirin_drm_platform_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct component_match *match = NULL; + struct device_node *remote; + + dc_ops = (struct kirin_dc_ops *)of_device_get_match_data(dev); + if (!dc_ops) { + DRM_ERROR("failed to get dt id data\n"); + return -EINVAL; + } + + remote = kirin_get_remote_node(np); + if (IS_ERR(remote)) + return PTR_ERR(remote); + + component_match_add(dev, &match, compare_of, remote); + + return component_master_add_with_match(dev, &kirin_drm_ops, match); + + return 0; +} + +static int kirin_drm_platform_remove(struct platform_device *pdev) +{ + component_master_del(&pdev->dev, &kirin_drm_ops); + dc_ops = NULL; + return 0; +} + +static const struct of_device_id kirin_drm_dt_ids[] = { + { .compatible = "hisilicon,hi3660-dpe", + .data = &dss_dc_ops, + }, + { /* end node */ }, +}; +MODULE_DEVICE_TABLE(of, kirin_drm_dt_ids); + +static struct platform_driver kirin_drm_platform_driver = { + .probe = kirin_drm_platform_probe, + .remove = kirin_drm_platform_remove, + .driver = { + .name = "kirin-drm", + .of_match_table = kirin_drm_dt_ids, + }, +}; + +module_platform_driver(kirin_drm_platform_driver); + +MODULE_AUTHOR("cailiwei <cailiwei@xxxxxxxxxxxxx>"); +MODULE_AUTHOR("zhengwanchun <zhengwanchun@xxxxxxxxxxxxx>"); +MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_drv.h b/drivers/staging/hikey9xx/gpu/kirin_drm_drv.h new file mode 100644 index 000000000000..b361f5f69932 --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/kirin_drm_drv.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 Linaro Limited. + * Copyright (c) 2014-2016 Hisilicon Limited. + * + * 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. + * + */ + +#ifndef __KIRIN_DRM_DRV_H__ +#define __KIRIN_DRM_DRV_H__ + +#include <drm/drmP.h> +#include <linux/ion.h> +#include <linux/hisi/hisi_ion.h> +#include <linux/hisi/hisi-iommu.h> + +#include "drm_crtc.h" +#include "drm_fb_helper.h" + +#define MAX_CRTC 2 + +#define to_kirin_fbdev(x) container_of(x, struct kirin_fbdev, fb_helper) + +/* display controller init/cleanup ops */ +struct kirin_dc_ops { + int (*init)(struct drm_device *dev); + void (*cleanup)(struct drm_device *dev); +}; + +struct kirin_drm_private { + struct drm_fb_helper *fb_helper; + struct drm_fb_helper *fbdev; + struct drm_crtc *crtc[MAX_CRTC]; +}; + +struct kirin_fbdev { + struct drm_fb_helper fb_helper; + struct drm_framebuffer *fb; + + struct ion_client *ion_client; + struct ion_handle *ion_handle; + struct iommu_map_format iommu_format; + void *screen_base; + unsigned long smem_start; + unsigned long screen_size; + int shared_fd; +}; + +extern const struct kirin_dc_ops dss_dc_ops; +extern void dsi_set_output_client(struct drm_device *dev); + +struct drm_framebuffer *kirin_framebuffer_init(struct drm_device *dev, + struct drm_mode_fb_cmd2 *mode_cmd); +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__ */ diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_dss.c b/drivers/staging/hikey9xx/gpu/kirin_drm_dss.c new file mode 100644 index 000000000000..2a92372d0c81 --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/kirin_drm_dss.c @@ -0,0 +1,701 @@ +/* + * Hisilicon Hi6220 SoC ADE(Advanced Display Engine)'s crtc&plane driver + * + * Copyright (c) 2016 Linaro Limited. + * Copyright (c) 2014-2016 Hisilicon Limited. + * + * Author: + * Xinliang Liu <z.liuxinliang@xxxxxxxxxxxxx> + * Xinliang Liu <xinliang.liu@xxxxxxxxxx> + * Xinwei Kong <kong.kongxinwei@xxxxxxxxxxxxx> + * + * 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. + * + */ + +#include <linux/bitops.h> +#include <linux/clk.h> +#include <video/display_timing.h> +#include <linux/mfd/syscon.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/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_plane_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fb_cma_helper.h> + +#include "kirin_drm_drv.h" + +#include "kirin_drm_dpe_utils.h" +#include "kirin_dpe_reg.h" + +#define DTS_COMP_DSS_NAME "hisilicon,hi3660-dpe" + +#define DSS_DEBUG 0 + +static const struct dss_format dss_formats[] = { + /* 16bpp RGB: */ + { DRM_FORMAT_RGB565, HISI_FB_PIXEL_FORMAT_RGB_565 }, + { DRM_FORMAT_BGR565, HISI_FB_PIXEL_FORMAT_BGR_565 }, + /* 32bpp [A]RGB: */ + { DRM_FORMAT_XRGB8888, HISI_FB_PIXEL_FORMAT_RGBX_8888 }, + { DRM_FORMAT_XBGR8888, HISI_FB_PIXEL_FORMAT_BGRX_8888 }, + { DRM_FORMAT_RGBA8888, HISI_FB_PIXEL_FORMAT_RGBA_8888 }, + { DRM_FORMAT_BGRA8888, HISI_FB_PIXEL_FORMAT_BGRA_8888 }, + /*{ DRM_FORMAT_ARGB8888, },*/ + /*{ DRM_FORMAT_ABGR8888, },*/ +}; + +static const u32 channel_formats1[] = { + DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, + DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888 +}; + +u32 dss_get_channel_formats(u8 ch, const u32 **formats) +{ + switch (ch) { + case DSS_CH1: + *formats = channel_formats1; + return ARRAY_SIZE(channel_formats1); + default: + DRM_ERROR("no this channel %d\n", ch); + *formats = NULL; + return 0; + } +} + +/* convert from fourcc format to dss format */ +u32 dss_get_format(u32 pixel_format) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dss_formats); i++) + if (dss_formats[i].pixel_format == pixel_format) + return dss_formats[i].dss_format; + + /* not found */ + DRM_ERROR("Not found pixel format!!fourcc_format= %d\n", + pixel_format); + return HISI_FB_PIXEL_FORMAT_UNSUPPORT; +} + +/******************************************************************************* + ** + */ +static void dss_ldi_set_mode(struct dss_crtc *acrtc) +{ + int ret; + u32 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; + } 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; + DRM_INFO("dss_pxl0_clk = %u\n", adj_mode->clock); + + dpe_init(acrtc); +} + +static int dss_power_up(struct dss_crtc *acrtc) +{ + int ret; + struct dss_hw_ctx *ctx = acrtc->ctx; + + ret = clk_prepare_enable(ctx->dss_pxl0_clk); + if (ret) { + DRM_ERROR("failed to enable dss_pxl0_clk (%d)\n", ret); + return ret; + } + + ret = clk_prepare_enable(ctx->dss_pri_clk); + if (ret) { + DRM_ERROR("failed to enable dss_pri_clk (%d)\n", ret); + return ret; + } + + ret = clk_prepare_enable(ctx->dss_pclk_dss_clk); + if (ret) { + DRM_ERROR("failed to enable dss_pclk_dss_clk (%d)\n", ret); + return ret; + } + + ret = clk_prepare_enable(ctx->dss_axi_clk); + if (ret) { + DRM_ERROR("failed to enable dss_axi_clk (%d)\n", ret); + return ret; + } + + ret = clk_prepare_enable(ctx->dss_mmbuf_clk); + if (ret) { + 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); + dpe_interrupt_mask(acrtc); + dpe_interrupt_clear(acrtc); + dpe_irq_enable(acrtc); + dpe_interrupt_unmask(acrtc); + + ctx->power_on = true; + return 0; +} + +#if 0 +static void dss_power_down(struct dss_crtc *acrtc) +{ + struct dss_hw_ctx *ctx = acrtc->ctx; + + dpe_interrupt_mask(acrtc); + dpe_irq_disable(acrtc); + + ctx->power_on = false; +} +#endif + +static int dss_enable_vblank(struct drm_device *dev, unsigned int pipe) +{ + struct kirin_drm_private *priv = dev->dev_private; + struct dss_crtc *acrtc = to_dss_crtc(priv->crtc[pipe]); + struct dss_hw_ctx *ctx = acrtc->ctx; + + if (!ctx->power_on) + (void)dss_power_up(acrtc); + + return 0; +} + +static void dss_disable_vblank(struct drm_device *dev, unsigned int pipe) +{ + struct kirin_drm_private *priv = dev->dev_private; + struct dss_crtc *acrtc = to_dss_crtc(priv->crtc[pipe]); + struct dss_hw_ctx *ctx = acrtc->ctx; + + if (!ctx->power_on) { + DRM_ERROR("power is down! vblank disable fail\n"); + return; + } +} + +static irqreturn_t dss_irq_handler(int irq, void *data) +{ + struct dss_crtc *acrtc = data; + struct dss_hw_ctx *ctx = acrtc->ctx; + void __iomem *dss_base = ctx->base; + + u32 isr_s1 = 0; + u32 isr_s2 = 0; + u32 isr_s2_dpp = 0; + u32 isr_s2_smmu = 0; + u32 mask = 0; + + 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); + + 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_START) { + ctx->vactive0_start_flag++; + wake_up_interruptible_all(&ctx->vactive0_start_wq); + } + + if (isr_s2 & BIT_VSYNC) + ctx->vsync_timestamp = ktime_get(); + + if (isr_s2 & BIT_LDI_UNFLOW) { + mask = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK); + mask |= BIT_LDI_UNFLOW; + outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, mask); + + DRM_ERROR("ldi underflow!\n"); + } + + return IRQ_HANDLED; +} + +static void dss_crtc_enable(struct drm_crtc *crtc) +{ + struct dss_crtc *acrtc = to_dss_crtc(crtc); + struct dss_hw_ctx *ctx = acrtc->ctx; + int ret; + + if (acrtc->enable) + return; + + if (!ctx->power_on) { + ret = dss_power_up(acrtc); + if (ret) + return; + } + + acrtc->enable = true; +} + +static void dss_crtc_disable(struct drm_crtc *crtc) +{ + struct dss_crtc *acrtc = to_dss_crtc(crtc); + + if (!acrtc->enable) + return; + + /*dss_power_down(acrtc);*/ + acrtc->enable = false; +} + +static int dss_crtc_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + /* do nothing */ + return 0; +} + +static void dss_crtc_mode_set_nofb(struct drm_crtc *crtc) +{ + struct dss_crtc *acrtc = to_dss_crtc(crtc); + struct dss_hw_ctx *ctx = acrtc->ctx; + + if (!ctx->power_on) + (void)dss_power_up(acrtc); + dss_ldi_set_mode(acrtc); +} + +static void dss_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + struct dss_crtc *acrtc = to_dss_crtc(crtc); + struct dss_hw_ctx *ctx = acrtc->ctx; + + if (!ctx->power_on) + (void)dss_power_up(acrtc); +} + +static void dss_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) + +{ + +} + +static const struct drm_crtc_helper_funcs dss_crtc_helper_funcs = { + .enable = dss_crtc_enable, + .disable = dss_crtc_disable, + .atomic_check = dss_crtc_atomic_check, + .mode_set_nofb = dss_crtc_mode_set_nofb, + .atomic_begin = dss_crtc_atomic_begin, + .atomic_flush = dss_crtc_atomic_flush, +}; + +static const struct drm_crtc_funcs dss_crtc_funcs = { + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .set_property = drm_atomic_helper_crtc_set_property, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static int dss_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, + struct drm_plane *plane) +{ + struct kirin_drm_private *priv = dev->dev_private; + struct device_node *port; + int ret; + + /* set crtc port so that + * drm_of_find_possible_crtcs call works + */ + port = of_get_child_by_name(dev->dev->of_node, "port"); + if (!port) { + DRM_ERROR("no port node found in %s\n", + dev->dev->of_node->full_name); + return -EINVAL; + } + of_node_put(port); + crtc->port = port; + + ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, + &dss_crtc_funcs); + if (ret) { + DRM_ERROR("failed to init crtc.\n"); + return ret; + } + + drm_crtc_helper_add(crtc, &dss_crtc_helper_funcs); + priv->crtc[drm_crtc_index(crtc)] = crtc; + + return 0; +} + +static int dss_plane_prepare_fb(struct drm_plane *plane, + const struct drm_plane_state *new_state) +{ + /* do nothing */ + return 0; +} + +static void dss_plane_cleanup_fb(struct drm_plane *plane, + const struct drm_plane_state *old_state) +{ + /* do nothing */ +} + +static int dss_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct drm_framebuffer *fb = state->fb; + struct drm_crtc *crtc = state->crtc; + struct drm_crtc_state *crtc_state; + u32 src_x = state->src_x >> 16; + u32 src_y = state->src_y >> 16; + u32 src_w = state->src_w >> 16; + u32 src_h = state->src_h >> 16; + int crtc_x = state->crtc_x; + int crtc_y = state->crtc_y; + u32 crtc_w = state->crtc_w; + u32 crtc_h = state->crtc_h; + u32 fmt; + + if (!crtc || !fb) + return 0; + + fmt = dss_get_format(fb->pixel_format); + if (fmt == HISI_FB_PIXEL_FORMAT_UNSUPPORT) + return -EINVAL; + + crtc_state = drm_atomic_get_crtc_state(state->state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + if (src_w != crtc_w || src_h != crtc_h) { + DRM_ERROR("Scale not support!!!\n"); + return -EINVAL; + } + + if (src_x + src_w > fb->width || + src_y + src_h > fb->height) + return -EINVAL; + + if (crtc_x < 0 || crtc_y < 0) + return -EINVAL; + + if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay || + crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay) + return -EINVAL; + + return 0; +} + +static void dss_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + hisi_fb_pan_display(plane); +} + +static void dss_plane_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + //struct dss_plane *aplane = to_dss_plane(plane); +} + +static const struct drm_plane_helper_funcs dss_plane_helper_funcs = { + .prepare_fb = dss_plane_prepare_fb, + .cleanup_fb = dss_plane_cleanup_fb, + .atomic_check = dss_plane_atomic_check, + .atomic_update = dss_plane_atomic_update, + .atomic_disable = dss_plane_atomic_disable, +}; + +static struct drm_plane_funcs dss_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .set_property = drm_atomic_helper_plane_set_property, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static int dss_plane_init(struct drm_device *dev, struct dss_plane *aplane, + enum drm_plane_type type) +{ + const u32 *fmts; + u32 fmts_cnt; + int ret = 0; + + /* get properties */ + fmts_cnt = dss_get_channel_formats(aplane->ch, &fmts); + if (ret) + return ret; + + ret = drm_universal_plane_init(dev, &aplane->base, 1, &dss_plane_funcs, + fmts, fmts_cnt, type); + if (ret) { + DRM_ERROR("fail to init plane, ch=%d\n", aplane->ch); + return ret; + } + + drm_plane_helper_add(&aplane->base, &dss_plane_helper_funcs); + + return 0; +} + +static int dss_enable_iommu(struct platform_device *pdev, struct dss_hw_ctx *ctx) +{ + struct device *dev = NULL; + + dev = &pdev->dev; + + /* create iommu domain */ + ctx->mmu_domain = iommu_domain_alloc(dev->bus); + if (!ctx->mmu_domain) { + pr_err("iommu_domain_alloc failed!\n"); + return -EINVAL; + } + + iommu_attach_device(ctx->mmu_domain, dev); + + return 0; +} + +static int dss_dts_parse(struct platform_device *pdev, struct dss_hw_ctx *ctx) +{ + struct device *dev = &pdev->dev; + struct device_node *np = NULL; + 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; + } + + ctx->base = of_iomap(np, 0); + if (!(ctx->base)) { + DRM_ERROR ("failed to get ade base resource.\n"); + return -ENXIO; + } + + 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; + } + + ctx->sctrl_base = of_iomap(np, 2); + if (!(ctx->sctrl_base)) { + DRM_ERROR ("failed to get ade 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"); + 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; + } + + /* get irq no */ + ctx->irq = irq_of_parse_and_map(np, 0); + if (ctx->irq <= 0) { + DRM_ERROR("failed to get irq_pdp resource.\n"); + return -ENXIO; + } + + DRM_INFO("dss irq = %d.", ctx->irq); + + 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; + } + + ctx->dss_axi_clk = devm_clk_get(dev, "aclk_dss"); + if (!ctx->dss_axi_clk) { + DRM_ERROR("failed to parse dss_axi_clk\n"); + return -ENODEV; + } + + 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; + } + + ctx->dss_pri_clk = devm_clk_get(dev, "clk_edc0"); + if (!ctx->dss_pri_clk) { + DRM_ERROR("failed to parse dss_pri_clk\n"); + 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; + } + + 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) { + DRM_ERROR("failed to parse dss_pxl0_clk\n"); + 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; + } + + 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; +} + +static int dss_drm_init(struct drm_device *dev) +{ + struct platform_device *pdev = dev->platformdev; + struct dss_data *dss; + struct dss_hw_ctx *ctx; + struct dss_crtc *acrtc; + struct dss_plane *aplane; + enum drm_plane_type type; + int ret; + int i; + + dss = devm_kzalloc(dev->dev, sizeof(*dss), GFP_KERNEL); + if (!dss) { + DRM_ERROR("failed to alloc dss_data\n"); + return -ENOMEM; + } + platform_set_drvdata(pdev, dss); + + ctx = &dss->ctx; + acrtc = &dss->acrtc; + acrtc->ctx = ctx; + acrtc->out_format = LCD_RGB888; + acrtc->bgr_fmt = LCD_RGB; + + ret = dss_dts_parse(pdev, ctx); + if (ret) + return ret; + + ctx->ion_client = NULL; + ctx->ion_handle = NULL; + ctx->screen_base = 0; + ctx->screen_size = 0; + ctx->smem_start = 0; + + ctx->vactive0_start_flag = 0; + init_waitqueue_head(&ctx->vactive0_start_wq); + + /* + * plane init + * TODO: Now only support primary plane, overlay planes + * need to do. + */ + for (i = 0; i < DSS_CH_NUM; i++) { + aplane = &dss->aplane[i]; + aplane->ch = i; + /*aplane->ctx = ctx;*/ + aplane->acrtc = acrtc; + type = i == PRIMARY_CH ? DRM_PLANE_TYPE_PRIMARY : + DRM_PLANE_TYPE_OVERLAY; + + ret = dss_plane_init(dev, aplane, type); + if (ret) + return ret; + } + + /* crtc init */ + ret = dss_crtc_init(dev, &acrtc->base, &dss->aplane[PRIMARY_CH].base); + if (ret) + return ret; + + /* vblank irq init */ + 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); + return ret; + } + + disable_irq(ctx->irq); + + dev->driver->get_vblank_counter = drm_vblank_no_hw_counter; + dev->driver->enable_vblank = dss_enable_vblank; + dev->driver->disable_vblank = dss_disable_vblank; + + return 0; +} + +static void dss_drm_cleanup(struct drm_device *dev) +{ + struct platform_device *pdev = dev->platformdev; + struct dss_data *dss = platform_get_drvdata(pdev); + struct drm_crtc *crtc = &dss->acrtc.base; + + drm_crtc_cleanup(crtc); +} + +const struct kirin_dc_ops dss_dc_ops = { + .init = dss_drm_init, + .cleanup = dss_drm_cleanup +}; diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c b/drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c new file mode 100644 index 000000000000..98ab748b8d8e --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c @@ -0,0 +1,1288 @@ +/* Copyright (c) 2008-2011, 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_plane_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fb_cma_helper.h> + +#include "kirin_drm_dpe_utils.h" +#include "kirin_drm_drv.h" + + +#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}; + +/* +** 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 */ + { + MIF_CH0_OFFSET, + AIF0_CH0_OFFSET, + AIF1_CH0_OFFSET, + MCTL_CTL_MUTEX_RCH0, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_FLUSH_EN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_OV_OEN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_STARTY, + DSS_MCTRL_SYS_OFFSET + MCTL_MOD0_DBG, + DSS_RCH_D0_DMA_OFFSET, + DSS_RCH_D0_DFC_OFFSET, + 0, + 0, + 0, + 0, + 0, + 0, + DSS_RCH_D0_CSC_OFFSET, + }, + + /* D1 */ + { + MIF_CH1_OFFSET, + AIF0_CH1_OFFSET, + AIF1_CH1_OFFSET, + MCTL_CTL_MUTEX_RCH1, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH1_FLUSH_EN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH1_OV_OEN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH1_STARTY, + DSS_MCTRL_SYS_OFFSET + MCTL_MOD1_DBG, + DSS_RCH_D1_DMA_OFFSET, + DSS_RCH_D1_DFC_OFFSET, + 0, + 0, + 0, + 0, + 0, + 0, + DSS_RCH_D1_CSC_OFFSET, + }, + + /* V0 */ + { + MIF_CH2_OFFSET, + AIF0_CH2_OFFSET, + AIF1_CH2_OFFSET, + MCTL_CTL_MUTEX_RCH2, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH2_FLUSH_EN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH2_OV_OEN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH2_STARTY, + DSS_MCTRL_SYS_OFFSET + MCTL_MOD2_DBG, + DSS_RCH_VG0_DMA_OFFSET, + DSS_RCH_VG0_DFC_OFFSET, + DSS_RCH_VG0_SCL_OFFSET, + DSS_RCH_VG0_SCL_LUT_OFFSET, + DSS_RCH_VG0_ARSR_OFFSET, + DSS_RCH_VG0_ARSR_LUT_OFFSET, + DSS_RCH_VG0_POST_CLIP_OFFSET, + DSS_RCH_VG0_PCSC_OFFSET, + DSS_RCH_VG0_CSC_OFFSET, + }, + + /* G0 */ + { + MIF_CH3_OFFSET, + AIF0_CH3_OFFSET, + AIF1_CH3_OFFSET, + MCTL_CTL_MUTEX_RCH3, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH3_FLUSH_EN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH3_OV_OEN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH3_STARTY, + DSS_MCTRL_SYS_OFFSET + MCTL_MOD3_DBG, + DSS_RCH_G0_DMA_OFFSET, + DSS_RCH_G0_DFC_OFFSET, + DSS_RCH_G0_SCL_OFFSET, + 0, + 0, + 0, + DSS_RCH_G0_POST_CLIP_OFFSET, + 0, + DSS_RCH_G0_CSC_OFFSET, + }, + + /* V1 */ + { + MIF_CH4_OFFSET, + AIF0_CH4_OFFSET, + AIF1_CH4_OFFSET, + MCTL_CTL_MUTEX_RCH4, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH4_FLUSH_EN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH4_OV_OEN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH4_STARTY, + DSS_MCTRL_SYS_OFFSET + MCTL_MOD4_DBG, + DSS_RCH_VG1_DMA_OFFSET, + DSS_RCH_VG1_DFC_OFFSET, + DSS_RCH_VG1_SCL_OFFSET, + DSS_RCH_VG1_SCL_LUT_OFFSET, + 0, + 0, + DSS_RCH_VG1_POST_CLIP_OFFSET, + 0, + DSS_RCH_VG1_CSC_OFFSET, + }, + + /* G1 */ + { + MIF_CH5_OFFSET, + AIF0_CH5_OFFSET, + AIF1_CH5_OFFSET, + MCTL_CTL_MUTEX_RCH5, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH5_FLUSH_EN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH5_OV_OEN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH5_STARTY, + DSS_MCTRL_SYS_OFFSET + MCTL_MOD5_DBG, + DSS_RCH_G1_DMA_OFFSET, + DSS_RCH_G1_DFC_OFFSET, + DSS_RCH_G1_SCL_OFFSET, + 0, + 0, + 0, + DSS_RCH_G1_POST_CLIP_OFFSET, + 0, + DSS_RCH_G1_CSC_OFFSET, + }, + + /* D2 */ + { + MIF_CH6_OFFSET, + AIF0_CH6_OFFSET, + AIF1_CH6_OFFSET, + MCTL_CTL_MUTEX_RCH6, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH6_FLUSH_EN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH6_OV_OEN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH6_STARTY, + DSS_MCTRL_SYS_OFFSET + MCTL_MOD6_DBG, + DSS_RCH_D2_DMA_OFFSET, + DSS_RCH_D2_DFC_OFFSET, + 0, + 0, + 0, + 0, + 0, + 0, + DSS_RCH_D2_CSC_OFFSET, + }, + + /* D3 */ + { + MIF_CH7_OFFSET, + AIF0_CH7_OFFSET, + AIF1_CH7_OFFSET, + MCTL_CTL_MUTEX_RCH7, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH7_FLUSH_EN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH7_OV_OEN, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH7_STARTY, + DSS_MCTRL_SYS_OFFSET + MCTL_MOD7_DBG, + DSS_RCH_D3_DMA_OFFSET, + DSS_RCH_D3_DFC_OFFSET, + 0, + 0, + 0, + 0, + 0, + 0, + DSS_RCH_D3_CSC_OFFSET, + }, + + /* W0 */ + { + MIF_CH8_OFFSET, + AIF0_CH8_OFFSET, + AIF1_CH8_OFFSET, + MCTL_CTL_MUTEX_WCH0, + DSS_MCTRL_SYS_OFFSET + MCTL_WCH0_FLUSH_EN, + DSS_MCTRL_SYS_OFFSET + MCTL_WCH0_OV_IEN, + 0, + 0, + DSS_WCH0_DMA_OFFSET, + DSS_WCH0_DFC_OFFSET, + 0, + 0, + 0, + 0, + 0, + 0, + DSS_WCH0_CSC_OFFSET, + }, + + /* W1 */ + { + MIF_CH9_OFFSET, + AIF0_CH9_OFFSET, + AIF1_CH9_OFFSET, + MCTL_CTL_MUTEX_WCH1, + DSS_MCTRL_SYS_OFFSET + MCTL_WCH1_FLUSH_EN, + DSS_MCTRL_SYS_OFFSET + MCTL_WCH1_OV_IEN, + 0, + 0, + DSS_WCH1_DMA_OFFSET, + DSS_WCH1_DFC_OFFSET, + 0, + 0, + 0, + 0, + 0, + 0, + DSS_WCH1_CSC_OFFSET, + }, + /* V2 */ + { + MIF_CH10_OFFSET, + AIF0_CH11_OFFSET, + AIF1_CH11_OFFSET, + MCTL_CTL_MUTEX_RCH8, + DSS_MCTRL_SYS_OFFSET + MCTL_RCH8_FLUSH_EN, + 0, + 0, + DSS_MCTRL_SYS_OFFSET + MCTL_MOD8_DBG, + DSS_RCH_VG2_DMA_OFFSET, + DSS_RCH_VG2_DFC_OFFSET, + DSS_RCH_VG2_SCL_OFFSET, + DSS_RCH_VG2_SCL_LUT_OFFSET, + 0, + 0, + DSS_RCH_VG2_POST_CLIP_OFFSET, + 0, + DSS_RCH_VG2_CSC_OFFSET, + }, + /* W2 */ + { + MIF_CH11_OFFSET, + AIF0_CH12_OFFSET, + AIF1_CH12_OFFSET, + MCTL_CTL_MUTEX_WCH2, + DSS_MCTRL_SYS_OFFSET + MCTL_WCH2_FLUSH_EN, + 0, + 0, + 0, + DSS_WCH2_DMA_OFFSET, + DSS_WCH2_DFC_OFFSET, + 0, + 0, + 0, + 0, + 0, + 0, + DSS_WCH2_CSC_OFFSET, + }, +}; + +/*lint +e785*/ +u32 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}; + +u32 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 */ +u32 g_dss_chn_sid_num[DSS_CHN_MAX_DEFINE] = { + 4, 1, 4, 4, 4, 4, 1, 1, 3, 3, 3, 2 +}; + +/* start idx of each channel */ +/* smrx_idx = g_dss_smmu_smrx_idx[chn_idx] + (0 ~ g_dss_chn_sid_num[chn_idx]) */ +u32 g_dss_smmu_smrx_idx[DSS_CHN_MAX_DEFINE] = { + 0, 4, 5, 9, 13, 17, 21, 22, 26, 29, 23, 32 +}; +u32 g_dss_mif_sid_map[DSS_CHN_MAX] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static int hisi_pixel_format_hal2dma(int format) +{ + int ret = 0; + + switch(format) { + case HISI_FB_PIXEL_FORMAT_RGB_565: + case HISI_FB_PIXEL_FORMAT_BGR_565: + ret = DMA_PIXEL_FORMAT_RGB_565; + break; + case HISI_FB_PIXEL_FORMAT_RGBX_4444: + case HISI_FB_PIXEL_FORMAT_BGRX_4444: + ret = DMA_PIXEL_FORMAT_XRGB_4444; + break; + case HISI_FB_PIXEL_FORMAT_RGBA_4444: + case HISI_FB_PIXEL_FORMAT_BGRA_4444: + ret = DMA_PIXEL_FORMAT_ARGB_4444; + break; + case HISI_FB_PIXEL_FORMAT_RGBX_5551: + case HISI_FB_PIXEL_FORMAT_BGRX_5551: + ret = DMA_PIXEL_FORMAT_XRGB_5551; + break; + case HISI_FB_PIXEL_FORMAT_RGBA_5551: + case HISI_FB_PIXEL_FORMAT_BGRA_5551: + ret = DMA_PIXEL_FORMAT_ARGB_5551; + break; + + case HISI_FB_PIXEL_FORMAT_RGBX_8888: + case HISI_FB_PIXEL_FORMAT_BGRX_8888: + ret = DMA_PIXEL_FORMAT_XRGB_8888; + break; + case HISI_FB_PIXEL_FORMAT_RGBA_8888: + case HISI_FB_PIXEL_FORMAT_BGRA_8888: + ret = DMA_PIXEL_FORMAT_ARGB_8888; + break; + + case HISI_FB_PIXEL_FORMAT_YUV_422_I: + case HISI_FB_PIXEL_FORMAT_YUYV_422_Pkg: + case HISI_FB_PIXEL_FORMAT_YVYU_422_Pkg: + case HISI_FB_PIXEL_FORMAT_UYVY_422_Pkg: + case HISI_FB_PIXEL_FORMAT_VYUY_422_Pkg: + ret = DMA_PIXEL_FORMAT_YUYV_422_Pkg; + break; + + case HISI_FB_PIXEL_FORMAT_YCbCr_422_P: + case HISI_FB_PIXEL_FORMAT_YCrCb_422_P: + ret = DMA_PIXEL_FORMAT_YUV_422_P_HP; + break; + case HISI_FB_PIXEL_FORMAT_YCbCr_420_P: + case HISI_FB_PIXEL_FORMAT_YCrCb_420_P: + ret = DMA_PIXEL_FORMAT_YUV_420_P_HP; + break; + + case HISI_FB_PIXEL_FORMAT_YCbCr_422_SP: + case HISI_FB_PIXEL_FORMAT_YCrCb_422_SP: + ret = DMA_PIXEL_FORMAT_YUV_422_SP_HP; + break; + case HISI_FB_PIXEL_FORMAT_YCbCr_420_SP: + case HISI_FB_PIXEL_FORMAT_YCrCb_420_SP: + ret = DMA_PIXEL_FORMAT_YUV_420_SP_HP; + break; + + default: + DRM_ERROR("not support format(%d)!\n", format); + ret = -1; + break; + } + + return ret; +} + +static int hisi_pixel_format_hal2dfc(int format) +{ + int ret = 0; + + switch (format) { + case HISI_FB_PIXEL_FORMAT_RGB_565: + ret = DFC_PIXEL_FORMAT_RGB_565; + break; + case HISI_FB_PIXEL_FORMAT_RGBX_4444: + ret = DFC_PIXEL_FORMAT_XBGR_4444; + break; + case HISI_FB_PIXEL_FORMAT_RGBA_4444: + ret = DFC_PIXEL_FORMAT_ABGR_4444; + break; + case HISI_FB_PIXEL_FORMAT_RGBX_5551: + ret = DFC_PIXEL_FORMAT_XBGR_5551; + break; + case HISI_FB_PIXEL_FORMAT_RGBA_5551: + ret = DFC_PIXEL_FORMAT_ABGR_5551; + break; + case HISI_FB_PIXEL_FORMAT_RGBX_8888: + ret = DFC_PIXEL_FORMAT_XBGR_8888; + break; + case HISI_FB_PIXEL_FORMAT_RGBA_8888: + ret = DFC_PIXEL_FORMAT_ABGR_8888; + break; + + case HISI_FB_PIXEL_FORMAT_BGR_565: + ret = DFC_PIXEL_FORMAT_BGR_565; + break; + case HISI_FB_PIXEL_FORMAT_BGRX_4444: + ret = DFC_PIXEL_FORMAT_XRGB_4444; + break; + case HISI_FB_PIXEL_FORMAT_BGRA_4444: + ret = DFC_PIXEL_FORMAT_ARGB_4444; + break; + case HISI_FB_PIXEL_FORMAT_BGRX_5551: + ret = DFC_PIXEL_FORMAT_XRGB_5551; + break; + case HISI_FB_PIXEL_FORMAT_BGRA_5551: + ret = DFC_PIXEL_FORMAT_ARGB_5551; + break; + case HISI_FB_PIXEL_FORMAT_BGRX_8888: + ret = DFC_PIXEL_FORMAT_XRGB_8888; + break; + case HISI_FB_PIXEL_FORMAT_BGRA_8888: + ret = DFC_PIXEL_FORMAT_ARGB_8888; + break; + + case HISI_FB_PIXEL_FORMAT_YUV_422_I: + case HISI_FB_PIXEL_FORMAT_YUYV_422_Pkg: + ret = DFC_PIXEL_FORMAT_YUYV422; + break; + case HISI_FB_PIXEL_FORMAT_YVYU_422_Pkg: + ret = DFC_PIXEL_FORMAT_YVYU422; + break; + case HISI_FB_PIXEL_FORMAT_UYVY_422_Pkg: + ret = DFC_PIXEL_FORMAT_UYVY422; + break; + case HISI_FB_PIXEL_FORMAT_VYUY_422_Pkg: + ret = DFC_PIXEL_FORMAT_VYUY422; + break; + + case HISI_FB_PIXEL_FORMAT_YCbCr_422_SP: + ret = DFC_PIXEL_FORMAT_YUYV422; + break; + case HISI_FB_PIXEL_FORMAT_YCrCb_422_SP: + ret = DFC_PIXEL_FORMAT_YVYU422; + break; + case HISI_FB_PIXEL_FORMAT_YCbCr_420_SP: + ret = DFC_PIXEL_FORMAT_YUYV422; + break; + case HISI_FB_PIXEL_FORMAT_YCrCb_420_SP: + ret = DFC_PIXEL_FORMAT_YVYU422; + break; + + case HISI_FB_PIXEL_FORMAT_YCbCr_422_P: + case HISI_FB_PIXEL_FORMAT_YCbCr_420_P: + ret = DFC_PIXEL_FORMAT_YUYV422; + break; + case HISI_FB_PIXEL_FORMAT_YCrCb_422_P: + case HISI_FB_PIXEL_FORMAT_YCrCb_420_P: + ret = DFC_PIXEL_FORMAT_YVYU422; + break; + + default: + DRM_ERROR("not support format(%d)!\n", format); + ret = -1; + break; + } + + return ret; +} + +static int hisi_dss_aif_ch_config(struct dss_hw_ctx *ctx, int chn_idx) +{ + void __iomem *aif0_ch_base; + int mid = 0; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + mid = mid_array[chn_idx]; + aif0_ch_base = ctx->base + g_dss_module_base[chn_idx][MODULE_AIF0_CHN]; + + set_reg(aif0_ch_base, 0x0, 1, 0); + set_reg(aif0_ch_base, (uint32_t)mid, 4, 4); + + return 0; +} + +static int hisi_dss_smmu_config(struct dss_hw_ctx *ctx, int chn_idx, bool mmu_enable) +{ + void __iomem *smmu_base; + u32 idx = 0, i = 0; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + smmu_base = ctx->base + DSS_SMMU_OFFSET; + + for (i = 0; i < g_dss_chn_sid_num[chn_idx]; i++) { + idx = g_dss_smmu_smrx_idx[chn_idx] + i; + 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); + } + + return 0; +} + +static int hisi_dss_mif_config(struct dss_hw_ctx *ctx, int chn_idx, bool mmu_enable) +{ + void __iomem *mif_base; + void __iomem *mif_ch_base; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + mif_base = ctx->base + DSS_MIF_OFFSET; + mif_ch_base = ctx->base + + g_dss_module_base[chn_idx][MODULE_MIF_CHN]; + + if (!mmu_enable) { + set_reg(mif_ch_base + MIF_CTRL1, 0x1, 1, 5); + } else { + set_reg(mif_ch_base + MIF_CTRL1, 0x00080000, 32, 0); + } + + return 0; +} + +int hisi_dss_mctl_mutex_lock(struct dss_hw_ctx *ctx) +{ + void __iomem *mctl_base; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + mctl_base = ctx->base + + g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE]; + + set_reg(mctl_base + MCTL_CTL_MUTEX, 0x1, 1, 0); + + return 0; +} + +int hisi_dss_mctl_mutex_unlock(struct dss_hw_ctx *ctx) +{ + void __iomem *mctl_base; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + mctl_base = ctx->base + + g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE]; + + set_reg(mctl_base + MCTL_CTL_MUTEX, 0x0, 1, 0); + + return 0; +} + +static int hisi_dss_mctl_ov_config(struct dss_hw_ctx *ctx, int chn_idx) +{ + void __iomem *mctl_base; + u32 mctl_rch_offset = 0; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + mctl_rch_offset = (uint32_t)(MCTL_CTL_MUTEX_RCH0 + chn_idx * 0x4); + + mctl_base = ctx->base + + g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE]; + + set_reg(mctl_base + MCTL_CTL_EN, 0x1, 32, 0); + set_reg(mctl_base + MCTL_CTL_TOP, 0x2, 32, 0); /*auto mode*/ + set_reg(mctl_base + MCTL_CTL_DBG, 0xB13A00, 32, 0); + + set_reg(mctl_base + mctl_rch_offset, 0x1, 32, 0); + set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 2, 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); + + return 0; +} + +static int hisi_dss_mctl_sys_config(struct dss_hw_ctx *ctx, int chn_idx) +{ + void __iomem *mctl_sys_base; + + u32 layer_idx = 0; + u32 mctl_rch_ov_oen_offset = 0; + u32 mctl_rch_flush_en_offset = 0; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET; + mctl_rch_ov_oen_offset = MCTL_RCH0_OV_OEN + chn_idx * 0x4; + mctl_rch_flush_en_offset = MCTL_RCH0_FLUSH_EN + chn_idx * 0x4; + + 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); + + set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, chn_idx, 4, (layer_idx + 1) * 4); + + set_reg(mctl_sys_base + MCTL_OV0_FLUSH_EN, 0xd, 4, 0); + set_reg(mctl_sys_base + mctl_rch_flush_en_offset, 0x1, 32, 0); + + return 0; +} + +static int hisi_dss_rdma_config(struct dss_hw_ctx *ctx, + const dss_rect_ltrb_t *rect, u32 display_addr, u32 hal_format, + u32 bpp, int chn_idx, bool afbcd, bool mmu_enable) +{ + void __iomem *rdma_base; + + u32 aligned_pixel = 0; + u32 rdma_oft_x0 = 0; + u32 rdma_oft_y0 = 0; + u32 rdma_oft_x1 = 0; + u32 rdma_oft_y1 = 0; + u32 rdma_stride = 0; + u32 rdma_bpp = 0; + u32 rdma_format = 0; + u32 stretch_size_vrt = 0; + + u32 stride_align = 0; + u32 mm_base_0 = 0; + u32 mm_base_1 = 0; + + u32 afbcd_header_addr = 0; + u32 afbcd_header_stride = 0; + u32 afbcd_payload_addr = 0; + u32 afbcd_payload_stride = 0; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + if (bpp == 4) { + rdma_bpp = 0x5; + } else if (bpp == 2) { + rdma_bpp = 0x0; + } else { + rdma_bpp = 0x0; + } + + rdma_base = ctx->base + + g_dss_module_base[chn_idx][MODULE_DMA]; + + aligned_pixel = DMA_ALIGN_BYTES / bpp; + rdma_oft_x0 = rect->left / aligned_pixel; + rdma_oft_y0 = rect->top; + rdma_oft_x1 = rect->right / aligned_pixel; + rdma_oft_y1 = rect->bottom; + + rdma_format = hisi_pixel_format_hal2dma(hal_format); + if (rdma_format < 0) { + DRM_ERROR("layer format(%d) not support !\n", hal_format); + return -EINVAL; + } + + if (afbcd) { + mm_base_0 = 0; + mm_base_1 = mm_base_0 + rect->right * bpp * MMBUF_LINE_NUM; + mm_base_0 = ALIGN_UP(mm_base_0, MMBUF_ADDR_ALIGN); + mm_base_1 = ALIGN_UP(mm_base_1, MMBUF_ADDR_ALIGN); + + if ((((rect->right - rect->left) + 1) & (AFBC_HEADER_ADDR_ALIGN - 1)) || + (((rect->bottom - rect->top) + 1) & (AFBC_BLOCK_ALIGN - 1))) { + DRM_ERROR("img width(%d) is not %d bytes aligned, or " + "img heigh(%d) is not %d bytes aligned!\n", + ((rect->right - rect->left) + 1), AFBC_HEADER_ADDR_ALIGN, + ((rect->bottom - rect->top) + 1), AFBC_BLOCK_ALIGN); + } + + if ((mm_base_0 & (MMBUF_ADDR_ALIGN - 1)) || (mm_base_1 & (MMBUF_ADDR_ALIGN - 1))) { + DRM_ERROR("mm_base_0(0x%x) is not %d bytes aligned, or " + "mm_base_1(0x%x) is not %d bytes aligned!\n", + mm_base_0, MMBUF_ADDR_ALIGN, + mm_base_1, MMBUF_ADDR_ALIGN); + } + /*header*/ + afbcd_header_stride = (((rect->right - rect->left) + 1) / AFBC_BLOCK_ALIGN) * AFBC_HEADER_STRIDE_BLOCK; + afbcd_header_addr = (uint32_t)(unsigned long)display_addr; + + /*payload*/ + if (bpp == 4) + stride_align = AFBC_PAYLOAD_STRIDE_ALIGN_32; + else if (bpp == 2) + stride_align = AFBC_PAYLOAD_STRIDE_ALIGN_16; + else + DRM_ERROR("bpp(%d) not supported!\n", bpp); + + afbcd_payload_stride = (((rect->right - rect->left) + 1) / AFBC_BLOCK_ALIGN) * stride_align; + + afbcd_payload_addr = afbcd_header_addr + ALIGN_UP(16 * (((rect->right - rect->left) + 1) / 16) * + (((rect->bottom - rect->top) + 1) / 16), 1024); + afbcd_payload_addr = afbcd_payload_addr + + (rect->top / AFBC_BLOCK_ALIGN) * afbcd_payload_stride + + (rect->left / AFBC_BLOCK_ALIGN) * stride_align; + + set_reg(rdma_base + CH_REG_DEFAULT, 0x1, 32, 0); + set_reg(rdma_base + CH_REG_DEFAULT, 0x0, 32, 0); + set_reg(rdma_base + DMA_OFT_X0, rdma_oft_x0, 12, 0); + 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_STRETCH_SIZE_VRT, (rect->bottom - rect->top), 13, 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 + AFBCD_HREG_PIC_WIDTH, (rect->right - rect->left), 16, 0); + set_reg(rdma_base + AFBCD_HREG_PIC_HEIGHT, (rect->bottom - rect->top), 16, 0); + set_reg(rdma_base + AFBCD_CTL, AFBC_HALF_BLOCK_UPPER_LOWER_ALL, 2, 6); + set_reg(rdma_base + AFBCD_HREG_HDR_PTR_LO, afbcd_header_addr, 32, 0); + set_reg(rdma_base + AFBCD_INPUT_HEADER_STRIDE, afbcd_header_stride, 14, 0); + set_reg(rdma_base + AFBCD_PAYLOAD_STRIDE, afbcd_payload_stride, 20, 0); + set_reg(rdma_base + AFBCD_MM_BASE_0, mm_base_0, 32, 0); + set_reg(rdma_base + AFBCD_HREG_FORMAT, 0x1, 1, 21); + set_reg(rdma_base + AFBCD_SCRAMBLE_MODE, 0x0, 32, 0); + set_reg(rdma_base + AFBCD_AFBCD_PAYLOAD_POINTER, afbcd_payload_addr, 32, 0); + set_reg(rdma_base + AFBCD_HEIGHT_BF_STR, (rect->bottom - rect->top), 16, 0); + + set_reg(rdma_base + CH_CTL, 0xf005, 32, 0); + } else { + stretch_size_vrt = rdma_oft_y1 - rdma_oft_y0; + rdma_stride = ((rect->right - rect->left) + 1) * bpp / DMA_ALIGN_BYTES; + + set_reg(rdma_base + CH_REG_DEFAULT, 0x1, 32, 0); + set_reg(rdma_base + CH_REG_DEFAULT, 0x0, 32, 0); + + set_reg(rdma_base + DMA_OFT_X0, rdma_oft_x0, 12, 0); + 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_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); + + set_reg(rdma_base + CH_CTL, 0x1, 1, 0); + } + + return 0; +} + +static int hisi_dss_rdfc_config(struct dss_hw_ctx *ctx, + const dss_rect_ltrb_t *rect, u32 hal_format, u32 bpp, int chn_idx) +{ + void __iomem *rdfc_base; + + u32 dfc_pix_in_num = 0; + u32 size_hrz = 0; + u32 size_vrt = 0; + u32 dfc_fmt = 0; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + rdfc_base = ctx->base + + g_dss_module_base[chn_idx][MODULE_DFC]; + + dfc_pix_in_num = (bpp <= 2) ? 0x1 : 0x0; + size_hrz = rect->right - rect->left; + size_vrt = rect->bottom - rect->top; + + dfc_fmt = hisi_pixel_format_hal2dfc(hal_format); + if (dfc_fmt < 0) { + DRM_ERROR("layer format (%d) not support !\n", hal_format); + return -EINVAL; + } + + set_reg(rdfc_base + DFC_DISP_SIZE, (size_vrt | (size_hrz << 16)), 29, 0); + set_reg(rdfc_base + DFC_PIX_IN_NUM, dfc_pix_in_num, 1, 0); + //set_reg(rdfc_base + DFC_DISP_FMT, (bpp <= 2) ? 0x0 : 0x6, 5, 1); + set_reg(rdfc_base + DFC_DISP_FMT, dfc_fmt, 5, 1); + set_reg(rdfc_base + DFC_CTL_CLIP_EN, 0x1, 1, 0); + set_reg(rdfc_base + DFC_ICG_MODULE, 0x1, 1, 0); + + return 0; +} + +int hisi_dss_ovl_base_config(struct dss_hw_ctx *ctx, u32 xres, u32 yres) +{ + void __iomem *mctl_sys_base; + void __iomem *mctl_base; + void __iomem *ovl0_base; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + 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); + + 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_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); + + return 0; +} + +static int hisi_dss_ovl_config(struct dss_hw_ctx *ctx, + const dss_rect_ltrb_t *rect, u32 xres, u32 yres) +{ + void __iomem *ovl0_base; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return -1; + } + + 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); + + return 0; +} + +static void hisi_dss_qos_on(struct dss_hw_ctx *ctx) +{ + char __iomem *noc_dss_base; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + noc_dss_base = ctx->noc_dss_base; + + outp32(noc_dss_base + 0xc, 0x2); + outp32(noc_dss_base + 0x8c, 0x2); + outp32(noc_dss_base + 0x10c, 0x2); + outp32(noc_dss_base + 0x18c, 0x2); +} + +static void hisi_dss_mif_on(struct dss_hw_ctx *ctx) +{ + char __iomem *dss_base; + char __iomem *mif_base; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + dss_base = ctx->base; + mif_base = ctx->base + DSS_MIF_OFFSET; + + set_reg(mif_base + MIF_ENABLE, 0x1, 1, 0); + set_reg(dss_base + MIF_CH0_OFFSET + MIF_CTRL0, 0x1, 1, 0); + set_reg(dss_base + MIF_CH1_OFFSET + MIF_CTRL0, 0x1, 1, 0); + set_reg(dss_base + MIF_CH2_OFFSET + MIF_CTRL0, 0x1, 1, 0); + set_reg(dss_base + MIF_CH3_OFFSET + MIF_CTRL0, 0x1, 1, 0); + set_reg(dss_base + MIF_CH4_OFFSET + MIF_CTRL0, 0x1, 1, 0); + set_reg(dss_base + MIF_CH5_OFFSET + MIF_CTRL0, 0x1, 1, 0); + set_reg(dss_base + MIF_CH6_OFFSET + MIF_CTRL0, 0x1, 1, 0); + set_reg(dss_base + MIF_CH7_OFFSET + MIF_CTRL0, 0x1, 1, 0); + set_reg(dss_base + MIF_CH8_OFFSET + MIF_CTRL0, 0x1, 1, 0); + set_reg(dss_base + MIF_CH9_OFFSET + MIF_CTRL0, 0x1, 1, 0); + + set_reg(dss_base + MIF_CH10_OFFSET + MIF_CTRL0, 0x1, 1, 0); + set_reg(dss_base + MIF_CH11_OFFSET + MIF_CTRL0, 0x1, 1, 0); +} + +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; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + smmu_base = ctx->base + DSS_SMMU_OFFSET; + + set_reg(smmu_base + SMMU_SCR, 0x0, 1, 0); /*global bypass cancel*/ + set_reg(smmu_base + SMMU_SCR, 0x1, 8, 20); /*ptw_mid*/ + set_reg(smmu_base + SMMU_SCR, 0xf, 4, 16); /*pwt_pf*/ + set_reg(smmu_base + SMMU_SCR, 0x7, 3, 3); /*interrupt cachel1 cach3l2 en*/ + set_reg(smmu_base + SMMU_LP_CTRL, 0x1, 1, 0); /*auto_clk_gt_en*/ + + /*Long Descriptor*/ + set_reg(smmu_base + SMMU_CB_TTBCR, 0x1, 1, 0); + + set_reg(smmu_base + SMMU_ERR_RDADDR, 0x7FF00000, 32, 0); + set_reg(smmu_base + SMMU_ERR_WRADDR, 0x7FFF0000, 32, 0); + + /*disable cmdlist, dbg, reload*/ + set_reg(smmu_base + SMMU_RLD_EN0_NS, DSS_SMMU_RLD_EN0_DEFAULT_VAL, 32, 0); + set_reg(smmu_base + SMMU_RLD_EN1_NS, DSS_SMMU_RLD_EN1_DEFAULT_VAL, 32, 0); + + /*cmdlist stream bypass*/ + set_reg(smmu_base + SMMU_SMRx_NS + 36 * 0x4, 0x1, 32, 0); /*debug stream id*/ + set_reg(smmu_base + SMMU_SMRx_NS + 37 * 0x4, 0x1, 32, 0); /*cmd unsec stream id*/ + set_reg(smmu_base + SMMU_SMRx_NS + 38 * 0x4, 0x1, 32, 0); /*cmd sec stream id*/ + + /*TTBR0*/ + domain_data = (struct iommu_domain_data *)(ctx->mmu_domain->priv); + phy_pgd_base = (uint32_t)(domain_data->phy_pgd_base); + set_reg(smmu_base + SMMU_CB_TTBR0, phy_pgd_base, 32, 0); +} + +void hisifb_dss_on(struct dss_hw_ctx *ctx) +{ + /* dss qos on*/ + hisi_dss_qos_on(ctx); + /* mif on*/ + hisi_dss_mif_on(ctx); + /* smmu on*/ + hisi_dss_smmu_on(ctx); +} + +void hisi_dss_mctl_on(struct dss_hw_ctx *ctx) +{ + char __iomem *mctl_base = NULL; + char __iomem *mctl_sys_base = NULL; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + mctl_base = ctx->base + + g_dss_module_ovl_base[DSS_MCTL0][MODULE_MCTL_BASE]; + mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET; + + set_reg(mctl_base + MCTL_CTL_EN, 0x1, 32, 0); + set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 32, 0); + set_reg(mctl_base + MCTL_CTL_DBG, 0xB13A00, 32, 0); + set_reg(mctl_base + MCTL_CTL_TOP, 0x2, 32, 0); +} + +void hisi_dss_unflow_handler(struct dss_hw_ctx *ctx, bool unmask) +{ + void __iomem *dss_base; + u32 tmp = 0; + + if (!ctx) { + DRM_ERROR("ctx is NULL!\n"); + return; + } + + dss_base = ctx->base; + + tmp = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK); + if (unmask) + tmp &= ~BIT_LDI_UNFLOW; + else + tmp |= BIT_LDI_UNFLOW; + + outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, tmp); +} + +static int hisi_vactive0_start_config(struct dss_hw_ctx *ctx) +{ + int ret = 0; + u32 times = 0; + u32 prev_vactive0_start = 0; + + prev_vactive0_start = ctx->vactive0_start_flag; + +REDO: + ret = wait_event_interruptible_timeout(ctx->vactive0_start_wq, + (prev_vactive0_start != ctx->vactive0_start_flag), + msecs_to_jiffies(300)); + if (ret == -ERESTARTSYS) { + if (times < 50) { + times++; + mdelay(10); + goto REDO; + } + } + + if (ret <= 0) { + DRM_ERROR("wait_for vactive0_start_flag timeout! ret=%d.\n", ret); + + ret = -ETIMEDOUT; + } else { + ret = 0; + } + + return ret; +} + +void hisi_fb_pan_display(struct drm_plane *plane) +{ + struct drm_plane_state *state = plane->state; + struct drm_framebuffer *fb = state->fb; + struct drm_display_mode *mode; + struct drm_display_mode *adj_mode; + + struct dss_plane *aplane = to_dss_plane(plane); + struct dss_crtc *acrtc = aplane->acrtc; + struct dss_hw_ctx *ctx = acrtc->ctx; + + struct kirin_drm_private *priv = plane->dev->dev_private; + struct kirin_fbdev *fbdev = to_kirin_fbdev(priv->fbdev); + + ktime_t prepare_timestamp; + u64 vsync_timediff; + + bool afbcd = false; + bool mmu_enable = true; + dss_rect_ltrb_t rect; + u32 bpp; + u32 stride; + u32 display_addr; + u32 hal_fmt; + int chn_idx = DSS_RCHN_D2; + + int crtc_x = state->crtc_x; + int crtc_y = state->crtc_y; + unsigned int crtc_w = state->crtc_w; + unsigned int crtc_h = state->crtc_h; + u32 src_x = state->src_x >> 16; + u32 src_y = state->src_y >> 16; + u32 src_w = state->src_w >> 16; + u32 src_h = state->src_h >> 16; + + u32 hfp, hbp, hsw, vfp, vbp, vsw; + + mode = &acrtc->base.state->mode; + adj_mode = &acrtc->base.state->adjusted_mode; + + bpp = fb->bits_per_pixel / 8; + stride = fb->pitches[0]; + + display_addr = (u32)fbdev->smem_start + src_y * stride; + + rect.left = 0; + rect.right = src_w - 1; + rect.top = 0; + rect.bottom = src_h - 1; + hal_fmt = 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", + chn_idx, src_x, src_y, src_w, src_h, + crtc_x, crtc_y, crtc_w, crtc_h, + rect.left, rect.top, rect.right, rect.bottom, + fb->width, fb->height, hal_fmt, + stride, display_addr, bpp, fb->bits_per_pixel); + + hfp = mode->hsync_start - mode->hdisplay; + hbp = mode->htotal - mode->hsync_end; + hsw = mode->hsync_end - mode->hsync_start; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + vsw = mode->vsync_end - mode->vsync_start; + + vsync_timediff = (uint64_t)(mode->hdisplay + hbp + hfp + hsw) * + (mode->vdisplay + vbp + vfp + vsw) * + 1000000000UL / (adj_mode->clock * 1000); + + prepare_timestamp = ktime_get(); + + if ((ktime_to_ns(prepare_timestamp) > ktime_to_ns(ctx->vsync_timestamp)) && + (ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp) < (vsync_timediff - 2000000)) && + (ktime_to_ns(ctx->vsync_timestamp_prev) != ktime_to_ns(ctx->vsync_timestamp))) { + DRM_DEBUG("vsync_timediff=%llu, timestamp_diff=%llu!\n", + vsync_timediff, ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp)); + } else { + DRM_DEBUG("vsync_timediff=%llu.\n", vsync_timediff); + + if (hisi_vactive0_start_config(ctx) != 0) { + DRM_ERROR("hisi_vactive0_start_config failed!\n"); + return; + } + } + ctx->vsync_timestamp_prev = ctx->vsync_timestamp; + + hisi_dss_mctl_mutex_lock(ctx); + hisi_dss_aif_ch_config(ctx, chn_idx); + hisi_dss_mif_config(ctx, chn_idx, mmu_enable); + hisi_dss_smmu_config(ctx, chn_idx, mmu_enable); + + 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_mctl_ov_config(ctx, chn_idx); + hisi_dss_mctl_sys_config(ctx, chn_idx); + hisi_dss_mctl_mutex_unlock(ctx); + + hisi_dss_unflow_handler(ctx, true); + + enable_ldi(acrtc); +} + +void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer) +{ + struct drm_plane_state *state = plane->state; + struct drm_display_mode *mode; + struct drm_display_mode *adj_mode; + + struct dss_plane *aplane = to_dss_plane(plane); + struct dss_crtc *acrtc = aplane->acrtc; + struct dss_hw_ctx *ctx = acrtc->ctx; + + ktime_t prepare_timestamp; + u64 vsync_timediff; + + bool afbcd = false; + bool mmu_enable = true; + dss_rect_ltrb_t rect; + u32 bpp; + u32 stride; + u32 display_addr; + + int chn_idx = DSS_RCHN_D2; + u32 hal_fmt = 0; + u32 src_w = state->src_w >> 16; + u32 src_h = state->src_h >> 16; + + u32 hfp, hbp, hsw, vfp, vbp, vsw; + + mode = &acrtc->base.state->mode; + adj_mode = &acrtc->base.state->adjusted_mode; + + bpp = layer->img.bpp; + stride = layer->img.stride; + display_addr = layer->img.vir_addr; + hal_fmt = layer->img.format; + + rect.left = 0; + rect.right = src_w - 1; + rect.top = 0; + rect.bottom = src_h - 1; + + hfp = mode->hsync_start - mode->hdisplay; + hbp = mode->htotal - mode->hsync_end; + hsw = mode->hsync_end - mode->hsync_start; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + vsw = mode->vsync_end - mode->vsync_start; + + vsync_timediff = (uint64_t)(mode->hdisplay + hbp + hfp + hsw) * + (mode->vdisplay + vbp + vfp + vsw) * + 1000000000UL / (adj_mode->clock * 1000); + + prepare_timestamp = ktime_get(); + + if ((ktime_to_ns(prepare_timestamp) > ktime_to_ns(ctx->vsync_timestamp)) && + (ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp) < (vsync_timediff - 2000000)) && + (ktime_to_ns(ctx->vsync_timestamp_prev) != ktime_to_ns(ctx->vsync_timestamp))) { + DRM_DEBUG("vsync_timediff=%llu, timestamp_diff=%llu!\n", + vsync_timediff, ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp)); + } else { + DRM_DEBUG("vsync_timediff=%llu.\n", vsync_timediff); + + if (hisi_vactive0_start_config(ctx) != 0) { + DRM_ERROR("hisi_vactive0_start_config failed!\n"); + return; + } + } + + ctx->vsync_timestamp_prev = ctx->vsync_timestamp; + + hisi_dss_mctl_mutex_lock(ctx); + hisi_dss_aif_ch_config(ctx, chn_idx); + hisi_dss_mif_config(ctx, chn_idx, mmu_enable); + hisi_dss_smmu_config(ctx, chn_idx, mmu_enable); + + 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_mctl_ov_config(ctx, chn_idx); + hisi_dss_mctl_sys_config(ctx, chn_idx); + hisi_dss_mctl_mutex_unlock(ctx); + + hisi_dss_unflow_handler(ctx, true); + + enable_ldi(acrtc); +} diff --git a/drivers/staging/hikey9xx/gpu/kirin_fb.c b/drivers/staging/hikey9xx/gpu/kirin_fb.c new file mode 100644 index 000000000000..834c9a381a4a --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/kirin_fb.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2013 Red Hat + * Author: Rob Clark <robdclark@xxxxxxxxx> + * + * 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 <drm/drmP.h> + +#include "kirin_drm_drv.h" + +#include "drm_crtc.h" +#include "drm_crtc_helper.h" + +struct kirin_framebuffer { + struct drm_framebuffer base; +}; +#define to_kirin_framebuffer(x) container_of(x, struct kirin_framebuffer, base) + + +static int kirin_framebuffer_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, + unsigned int *handle) +{ + //struct kirin_framebuffer *kirin_fb = to_kirin_framebuffer(fb); + return 0; +} + +static void kirin_framebuffer_destroy(struct drm_framebuffer *fb) +{ + struct kirin_framebuffer *kirin_fb = to_kirin_framebuffer(fb); + + DRM_DEBUG("destroy: FB ID: %d (%p)", fb->base.id, fb); + + drm_framebuffer_cleanup(fb); + + kfree(kirin_fb); +} + +static int kirin_framebuffer_dirty(struct drm_framebuffer *fb, + struct drm_file *file_priv, unsigned flags, unsigned color, + struct drm_clip_rect *clips, unsigned num_clips) +{ + return 0; +} + +static const struct drm_framebuffer_funcs kirin_framebuffer_funcs = { + .create_handle = kirin_framebuffer_create_handle, + .destroy = kirin_framebuffer_destroy, + .dirty = kirin_framebuffer_dirty, +}; + +struct drm_framebuffer *kirin_framebuffer_init(struct drm_device *dev, + struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct kirin_framebuffer *kirin_fb = NULL; + struct drm_framebuffer *fb; + int ret; + + kirin_fb = kzalloc(sizeof(*kirin_fb), GFP_KERNEL); + if (!kirin_fb) { + ret = -ENOMEM; + goto fail; + } + + fb = &kirin_fb->base; + + drm_helper_mode_fill_fb_struct(fb, mode_cmd); + + ret = drm_framebuffer_init(dev, fb, &kirin_framebuffer_funcs); + if (ret) { + dev_err(dev->dev, "framebuffer init failed: %d\n", ret); + goto fail; + } + + DRM_DEBUG("create: FB ID: %d (%p)", fb->base.id, fb); + + return fb; + +fail: + kfree(kirin_fb); + + return ERR_PTR(ret); +} diff --git a/drivers/staging/hikey9xx/gpu/kirin_fbdev.c b/drivers/staging/hikey9xx/gpu/kirin_fbdev.c new file mode 100644 index 000000000000..424a4107db56 --- /dev/null +++ b/drivers/staging/hikey9xx/gpu/kirin_fbdev.c @@ -0,0 +1,470 @@ +/* + * Copyright (C) 2013 Red Hat + * Author: Rob Clark <robdclark@xxxxxxxxx> + * + * 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 <drm/drmP.h> +#include <drm_crtc_helper.h> + +#include <linux/ion.h> +#include <linux/hisi/hisi_ion.h> + +#include "kirin_drm_drv.h" +#include "kirin_dpe_reg.h" +#include "kirin_drm_dpe_utils.h" + +#include "drm_crtc.h" +#include "drm_fb_helper.h" + +//#define CONFIG_HISI_FB_HEAP_CARVEOUT_USED + +#define FBDEV_BUFFER_NUM 3 +struct fb_dmabuf_export +{ + __u32 fd; + __u32 flags; +}; +#define FBIOGET_DMABUF _IOR('F', 0x21, struct fb_dmabuf_export) + +#define HISIFB_IOCTL_MAGIC 'M' +#define HISI_DRM_ONLINE_PLAY _IOW(HISIFB_IOCTL_MAGIC, 0x21, struct drm_dss_layer) + +/* + * fbdev funcs, to implement legacy fbdev interface on top of drm driver + */ + +#define HISI_FB_ION_CLIENT_NAME "hisi_fb_ion" + +unsigned long kirin_alloc_fb_buffer(struct kirin_fbdev *fbdev, int size) +{ + struct ion_client *client = NULL; + struct ion_handle *handle = NULL; + size_t buf_len = 0; + unsigned long buf_addr = 0; + int shared_fd = -1; + + if (NULL == fbdev) { + DRM_ERROR("fbdev is NULL!\n"); + return -EINVAL; + } + + client = fbdev->ion_client; + handle = fbdev->ion_handle; + + buf_len = size; + + client = hisi_ion_client_create(HISI_FB_ION_CLIENT_NAME); + if (!client) { + DRM_ERROR("failed to create ion client!\n"); + return -ENOMEM; + } + memset(&fbdev->iommu_format, 0, sizeof(struct iommu_map_format)); + +#ifdef CONFIG_HISI_FB_HEAP_CARVEOUT_USED + handle = ion_alloc(client, buf_len, PAGE_SIZE, ION_HEAP(ION_GRALLOC_HEAP_ID), 0); +#else + handle = ion_alloc(client, buf_len, PAGE_SIZE, ION_HEAP(ION_SYSTEM_HEAP_ID), 0); +#endif + if (!handle) { + DRM_ERROR("failed to ion_alloc!\n"); + goto err_return; + } + + fbdev->screen_base = ion_map_kernel(client, handle); + if (!fbdev->screen_base) { + DRM_ERROR("failed to ion_map_kernel!\n"); + goto err_ion_map; + } + +#ifdef CONFIG_HISI_FB_HEAP_CARVEOUT_USED + if (ion_phys(client, handle, &buf_addr, &buf_len) < 0) { + DRM_ERROR("failed to get ion phys!\n"); + goto err_ion_get_addr; + } +#else + if (ion_map_iommu(client, handle, &(fbdev->iommu_format))) { + DRM_ERROR("failed to ion_map_iommu!\n"); + goto err_ion_get_addr; + } + + buf_addr = fbdev->iommu_format.iova_start; +#endif + + fbdev->shared_fd = shared_fd; + fbdev->smem_start = buf_addr; + fbdev->screen_size = buf_len; + memset(fbdev->screen_base, 0x0, fbdev->screen_size); + + fbdev->ion_client = client; + fbdev->ion_handle = handle; + + return buf_addr; + +err_ion_get_addr: + ion_unmap_kernel(client, handle); +err_ion_map: + ion_free(client, handle); +err_return: + return 0; +} + +static int kirin_fbdev_mmap(struct fb_info *info, struct vm_area_struct * vma) +{ + struct sg_table *table = NULL; + struct scatterlist *sg = NULL; + struct page *page = NULL; + unsigned long remainder = 0; + unsigned long len = 0; + unsigned long addr = 0; + unsigned long offset = 0; + unsigned long size = 0; + int i = 0; + int ret = 0; + + struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par; + struct kirin_fbdev *fbdev = to_kirin_fbdev(helper); + + if (NULL == info) { + DRM_ERROR("info is NULL!\n"); + return -EINVAL; + } + + if (NULL == fbdev) { + DRM_ERROR("fbdev is NULL!\n"); + return -EINVAL; + } + + table = ion_sg_table(fbdev->ion_client, fbdev->ion_handle); + if ((table == NULL) || (vma == NULL)) { + DRM_ERROR("table or vma is NULL!\n"); + return -EFAULT; + } + + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + addr = vma->vm_start; + offset = vma->vm_pgoff * PAGE_SIZE; + size = vma->vm_end - vma->vm_start; + + if (size > info->fix.smem_len) { + DRM_ERROR("size=%lu is out of range(%u)!\n", size, info->fix.smem_len); + return -EFAULT; + } + + for_each_sg(table->sgl, sg, table->nents, i) { + page = sg_page(sg); + remainder = vma->vm_end - addr; + len = sg->length; + + if (offset >= sg->length) { + offset -= sg->length; + continue; + } else if (offset) { + page += offset / PAGE_SIZE; + len = sg->length - offset; + offset = 0; + } + len = min(len, remainder); + ret = remap_pfn_range(vma, addr, page_to_pfn(page), len, + vma->vm_page_prot); + if (ret != 0) { + DRM_ERROR("failed to remap_pfn_range! ret=%d\n", ret); + } + + addr += len; + if (addr >= vma->vm_end) + return 0; + } + + return 0; +} + +static int kirin_dmabuf_export(struct fb_info *info, void __user *argp) +{ + int ret; + struct drm_fb_helper *helper; + struct kirin_fbdev *fbdev; + struct fb_dmabuf_export dmabuf_export; + + helper = (struct drm_fb_helper *)info->par; + fbdev = to_kirin_fbdev(helper); + + ret = copy_from_user(&dmabuf_export, argp, sizeof(struct fb_dmabuf_export)); + if (ret) { + DRM_ERROR("copy for user failed!ret=%d.\n", ret); + ret = -EINVAL; + } else { + dmabuf_export.flags = 0; + dmabuf_export.fd = ion_share_dma_buf_fd(fbdev->ion_client, fbdev->ion_handle); + if (dmabuf_export.fd < 0) { + DRM_ERROR("failed to ion_share!\n"); + } + + ret = copy_to_user(argp, &dmabuf_export, sizeof(struct fb_dmabuf_export)); + if (ret) { + DRM_ERROR("copy to user failed!ret=%d.", ret); + ret = -EFAULT; + } + } + + return ret; +} + +static int kirin_dss_online_compose(struct fb_info *info, void __user *argp) +{ + int ret; + struct drm_fb_helper *helper; + struct kirin_drm_private *priv; + struct drm_plane *plane; + + struct drm_dss_layer layer; + + helper = (struct drm_fb_helper *)info->par; + priv = helper->dev->dev_private; + plane =priv->crtc[0]->primary; + + ret = copy_from_user(&layer, argp, sizeof(struct drm_dss_layer)); + if (ret) { + DRM_ERROR("copy for user failed!ret=%d.\n", ret); + return -EINVAL; + } + + hisi_dss_online_play(plane, &layer); + + return ret; +} + +static int kirin_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +{ + int ret = -ENOSYS; + void __user *argp = (void __user *)arg; + + if (NULL == info) { + DRM_ERROR("info is NULL!\n"); + return -EINVAL; + } + + switch (cmd) { + case FBIOGET_DMABUF: + ret = kirin_dmabuf_export(info, argp); + break; + case HISI_DRM_ONLINE_PLAY: + ret = kirin_dss_online_compose(info, argp); + break; + default: + break; + } + + if (ret == -ENOSYS) + DRM_ERROR("unsupported ioctl (%x)\n", cmd); + + return ret; +} + + +static struct fb_ops kirin_fb_ops = { + .owner = THIS_MODULE, + + /* Note: to properly handle manual update displays, we wrap the + * basic fbdev ops which write to the framebuffer + */ + .fb_read = drm_fb_helper_sys_read, + .fb_write = drm_fb_helper_sys_write, + .fb_fillrect = drm_fb_helper_sys_fillrect, + .fb_copyarea = drm_fb_helper_sys_copyarea, + .fb_imageblit = drm_fb_helper_sys_imageblit, + .fb_mmap = kirin_fbdev_mmap, + + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_blank = drm_fb_helper_blank, + .fb_setcmap = drm_fb_helper_setcmap, + + .fb_ioctl = kirin_fb_ioctl, + .fb_compat_ioctl = kirin_fb_ioctl, +}; + +static int kirin_fbdev_create(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct kirin_fbdev *fbdev = to_kirin_fbdev(helper); + struct drm_device *dev = helper->dev; + struct drm_framebuffer *fb = NULL; + struct fb_info *fbi = NULL; + struct drm_mode_fb_cmd2 mode_cmd = {0}; + int ret, size; + unsigned int bytes_per_pixel; + + DRM_DEBUG("create fbdev: %dx%d@%d (%dx%d)\n", sizes->surface_width, + sizes->surface_height, sizes->surface_bpp, + sizes->fb_width, sizes->fb_height); + + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height * FBDEV_BUFFER_NUM; + + bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); + mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; + //mode_cmd.pitches[0] = align_pitch(mode_cmd.width, sizes->surface_bpp); + + /* allocate backing bo */ + size = mode_cmd.pitches[0] * mode_cmd.height; + DRM_DEBUG("allocating %d bytes for fb %d", size, dev->primary->index); + + fb = kirin_framebuffer_init(dev, &mode_cmd); + if (IS_ERR(fb)) { + dev_err(dev->dev, "failed to allocate fb\n"); + /* note: if fb creation failed, we can't rely on fb destroy + * to unref the bo: + */ + ret = PTR_ERR(fb); + goto fail; + } + + mutex_lock(&dev->struct_mutex); + + fbdev->ion_client = NULL; + fbdev->ion_handle = NULL; + fbdev->screen_base = NULL; + fbdev->smem_start = 0; + fbdev->screen_size = 0; + memset(&fbdev->iommu_format, 0, sizeof(struct iommu_map_format)); + + kirin_alloc_fb_buffer(fbdev, size); + + fbi = drm_fb_helper_alloc_fbi(helper); + if (IS_ERR(fbi)) { + dev_err(dev->dev, "failed to allocate fb info\n"); + ret = PTR_ERR(fbi); + goto fail_unlock; + } + + DRM_DEBUG("fbi=%p, dev=%p", fbi, dev); + + fbdev->fb = fb; + helper->fb = fb; + + fbi->par = helper; + fbi->flags = FBINFO_DEFAULT; + fbi->fbops = &kirin_fb_ops; + + strcpy(fbi->fix.id, "dss"); + + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); + + dev->mode_config.fb_base = fbdev->smem_start; + fbi->screen_base = fbdev->screen_base; + fbi->screen_size = fbdev->screen_size; + 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); + + mutex_unlock(&dev->struct_mutex); + + return 0; + +fail_unlock: + mutex_unlock(&dev->struct_mutex); +fail: + if (ret) { + if (fb) { + drm_framebuffer_unregister_private(fb); + drm_framebuffer_remove(fb); + } + } + return ret; +} + +static const struct drm_fb_helper_funcs kirin_fb_helper_funcs = { + .fb_probe = kirin_fbdev_create, +}; + +/* initialize fbdev helper */ +struct drm_fb_helper *kirin_drm_fbdev_init(struct drm_device *dev) +{ + struct kirin_drm_private *priv = dev->dev_private; + struct kirin_fbdev *fbdev = NULL; + struct drm_fb_helper *helper; + int ret; + + fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); + if (!fbdev) + goto fail; + + priv->fb_helper = helper = &fbdev->fb_helper; + + drm_fb_helper_prepare(dev, helper, &kirin_fb_helper_funcs); + + DRM_INFO("num_crtc=%d, num_connector=%d.\n", + dev->mode_config.num_crtc, dev->mode_config.num_connector); + + ret = drm_fb_helper_init(dev, helper, + dev->mode_config.num_crtc, dev->mode_config.num_connector); + if (ret) { + dev_err(dev->dev, "could not init fbdev: ret=%d\n", ret); + goto fail; + } + + ret = drm_fb_helper_single_add_all_connectors(helper); + if (ret) + goto fini; + + /* disable all the possible outputs/crtcs before entering KMS mode */ + drm_helper_disable_unused_functions(dev); + + ret = drm_fb_helper_initial_config(helper, 32); + if (ret) + goto fini; + + priv->fbdev = helper; + + return helper; + +fini: + drm_fb_helper_fini(helper); +fail: + kfree(fbdev); + return NULL; +} + +void kirin_drm_fbdev_fini(struct drm_device *dev) +{ + struct kirin_drm_private *priv = dev->dev_private; + struct drm_fb_helper *helper = priv->fbdev; + struct kirin_fbdev *fbdev; + + drm_fb_helper_unregister_fbi(helper); + drm_fb_helper_release_fbi(helper); + + drm_fb_helper_fini(helper); + + fbdev = to_kirin_fbdev(priv->fbdev); + + /* this will free the backing object */ + if (fbdev->fb) { + drm_framebuffer_unregister_private(fbdev->fb); + drm_framebuffer_remove(fbdev->fb); + } + + kfree(fbdev); + + priv->fbdev = NULL; +} -- 2.26.2 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel