From: keith.zhao Date: Fri, 24 Jun 2022 13:51:16 +0000 (+0800) Subject: riscv:driver:drm:DC8200 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=79c1c35981c07ffb56e6a5ec4a2431dca9ed34c9;p=platform%2Fkernel%2Flinux-starfive.git riscv:driver:drm:DC8200 1、support 1080P 720P 480P display mode 2、replace some FW interface by using system api Signed-off-by:keith.zhao --- diff --git a/drivers/gpu/drm/verisilicon/inno_hdmi.c b/drivers/gpu/drm/verisilicon/inno_hdmi.c old mode 100644 new mode 100755 index 40fe808..9544c8a --- a/drivers/gpu/drm/verisilicon/inno_hdmi.c +++ b/drivers/gpu/drm/verisilicon/inno_hdmi.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -77,6 +78,8 @@ struct inno_hdmi { struct drm_display_mode previous_mode; struct regulator *hdmi_1p8; struct regulator *hdmi_0p9; + struct pre_pll_config *pre_cfg; + struct post_pll_config *post_cfg; }; enum { @@ -88,6 +91,59 @@ enum { CSC_RGB_0_255_TO_RGB_16_235_8BIT, }; +static const struct pre_pll_config pre_pll_cfg_table[] = { + { 25200000, 25200000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0}, + { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0}, + { 27000000, 33750000, 1, 90, 1, 3, 3, 10, 3, 3, 4, 0, 0}, + { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0}, + { 59341000, 59341000, 1, 98, 3, 1, 2, 1, 3, 3, 4, 0, 0xE6AE6B}, + { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0}, + { 59341000, 74176250, 1, 98, 0, 3, 3, 1, 3, 3, 4, 0, 0xE6AE6B}, + { 59400000, 74250000, 1, 99, 1, 2, 2, 1, 3, 3, 4, 0, 0}, + { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B}, + { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0}, + { 74176000, 92720000, 4, 494, 1, 2, 2, 1, 3, 3, 4, 0, 0x816817}, + { 74250000, 92812500, 4, 495, 1, 2, 2, 1, 3, 3, 4, 0, 0}, + {148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B}, + {148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0}, + {148352000, 185440000, 4, 494, 0, 2, 2, 1, 3, 2, 2, 0, 0x816817}, + {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0}, + {296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B}, + {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0}, + {296703000, 370878750, 4, 494, 1, 2, 0, 1, 3, 1, 1, 0, 0x816817}, + {297000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 0, 0}, + {593407000, 296703500, 1, 98, 0, 1, 1, 1, 0, 2, 1, 0, 0xE6AE6B}, + {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 1, 0, 0}, + {593407000, 370879375, 4, 494, 1, 2, 0, 1, 3, 1, 1, 1, 0x816817}, + {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0}, + {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B}, + {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0}, + { /* sentinel */ } +}; + +static const struct post_pll_config post_pll_cfg_table[] = { + {25200000, 1, 80, 7, 0,1}, + {27000000, 1, 40, 3, 0,1}, + {33750000, 1, 40, 8, 3,1}, + //{33750000, 1, 80, 8, 2}, + {74250000, 1, 20, 1, 3,1}, + //{74250000, 18, 80, 8, 2}, + {148500000, 1, 20, 1, 3,3}, + {297000000, 2, 20, 0, 3,3}, + {594000000, 4, 20, 0, 0,0},//postpll_postdiv_en = 0 + { /* sentinel */ } +}; +/* +static const struct post_pll_config post_pll_cfg_table[] = { + {33750000, 1, 40, 8, 1}, + {33750000, 1, 80, 8, 2}, + {74250000, 1, 40, 8, 1}, + {74250000, 18, 80, 8, 2}, + {148500000, 2, 40, 4, 3}, + {297000000, 4, 40, 2, 3}, + {594000000, 8, 40, 1, 3}, +}; +*/ static const char coeff_csc[][24] = { /* * YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]): @@ -202,9 +258,6 @@ static void inno_hdmi_power_up(struct inno_hdmi *hdmi) val &= ~(0x1); writel_relaxed(val, hdmi->regs + (0x1aa) * 0x04); - /*wait for pre-PLL and post-PLL lock*/ - //while(!(hdmi_read(word_align(0x1a9)) & 0x1)); - //while(!(hdmi_read(word_align(0x1af)) & 0x1)); while (!(readl_relaxed(hdmi->regs + (0x1a9) * 0x04) & 0x1)) ; while (!(readl_relaxed(hdmi->regs + (0x1af) * 0x04) & 0x1)) @@ -222,42 +275,43 @@ static void inno_hdmi_tx_phy_power_down(struct inno_hdmi *hdmi) writel_relaxed(0x63, hdmi->regs + (0x00) * 0x04); } -typedef struct register_value { - u16 reg; - u8 value; -} reg_value_t; - -#if 0 -static void inno_hdmi_config_640x480p60(struct inno_hdmi *hdmi) +static void inno_hdmi_config_pll(struct inno_hdmi *hdmi) { + u8 reg_1ad_value = hdmi->post_cfg->post_div_en ? + hdmi->post_cfg->postdiv : 0x0d; const reg_value_t cfg_pll_data[] = { - /* config pll: 640x480p, 60hz*/ {0x1a0, 0x01}, - //{0x1aa, 0x0f}, - {0x1a1, 0x01}, - {0x1a2, 0xf0}, - {0x1a3, 0x64}, - {0x1a4, 0x2f}, - //{0x1a4, 0x2a}, - {0x1a5, 0x6c}, - {0x1a6, 0x64}, - {0x1ab, 0x01}, - {0x1ac, 0x50}, - //{0x1ad, 0x07}, - {0x1ad, 0x0d}, + {0x1aa, 0x0f}, + {0x1a1, hdmi->pre_cfg->prediv}, + {0x1a2, 0xf0 | hdmi->pre_cfg->fbdiv>>8}, + {0x1a3, hdmi->pre_cfg->fbdiv}, + {0x1a4, ((hdmi->pre_cfg->tmds_div_a << 4) | (hdmi->pre_cfg->tmds_div_b << 2) | (hdmi->pre_cfg->tmds_div_c))}, + {0x1a5, (hdmi->pre_cfg->pclk_div_b << 5) | hdmi->pre_cfg->pclk_div_a}, + {0x1a6, (hdmi->pre_cfg->pclk_div_c << 5) | hdmi->pre_cfg->pclk_div_d}, + {0x1ab, hdmi->post_cfg->prediv}, + {0x1ac, hdmi->post_cfg->fbdiv & 0xff}, + {0x1ad, reg_1ad_value}, {0x1aa, 0x0e}, {0x1a0, 0x00}, }; int i; - - for (i = 0; i < sizeof(cfg_pll_data) / sizeof(reg_value_t); i++) { - //hdmi_write(cfg_pll_data[i].value, word_align(cfg_pll_data[i].reg)); + for (i = 0; i < sizeof(cfg_pll_data) / sizeof(reg_value_t); i++) + { + /* + if(0x1ad == cfg_pll_data[i].reg) + { + if(0 == hdmi->post_cfg->post_div_en) + { + writel_relaxed(0x0d, hdmi->regs + (cfg_pll_data[i].reg) * 0x04); + continue; + } + }*/ + dev_info(hdmi->dev, "%s %d reg[%02x],val[%02x]\n",__func__, __LINE__,cfg_pll_data[i].reg,cfg_pll_data[i].value); writel_relaxed(cfg_pll_data[i].value, hdmi->regs + (cfg_pll_data[i].reg) * 0x04); } return; } -#endif static void inno_hdmi_config_1920x1080p60(struct inno_hdmi *hdmi) { @@ -599,11 +653,244 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, return 0; } + static const + struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi *hdmi, + unsigned long rate) + { + const struct pre_pll_config *cfg = pre_pll_cfg_table; + //unsigned long tmdsclock = 148500000; + rate = (rate / 1000) * 1000; + + for (; cfg->pixclock != 0; cfg++) + if (cfg->pixclock == rate) + break; + + if (cfg->pixclock == 0) + return ERR_PTR(-EINVAL); + + return cfg; + } + +#define PRE_PLL_POWER_DOWN BIT(0) + + /* phy tuning values for an undocumented set of registers */ + static const struct phy_config inno_phy_cfg[] = { + { 165000000, { + 0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08, + 0x00, 0xac, 0xcc, 0xcc, 0xcc, + }, + }, { + 340000000, { + 0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08, + 0x3f, 0xac, 0xcc, 0xcd, 0xdd, + }, + }, { + 594000000, { + 0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08, + 0x00, 0xac, 0xcc, 0xcc, 0xcc, + }, + }, { /* sentinel */ }, + }; + + static int inno_hdmi_phy_clk_set_rate(struct inno_hdmi *hdmi,unsigned long rate) + { + hdmi->post_cfg = post_pll_cfg_table; + unsigned long tmdsclock = hdmi->tmds_rate; + u32 v; + int ret; + + dev_info(hdmi->dev, "%s rate %lu tmdsclk %lu\n",__func__, rate, tmdsclock); + + hdmi->pre_cfg = inno_hdmi_phy_get_pre_pll_cfg(hdmi, tmdsclock); + if (IS_ERR(hdmi->pre_cfg)) + return PTR_ERR(hdmi->pre_cfg); + + for (; hdmi->post_cfg->tmdsclock != 0; hdmi->post_cfg++) + if (tmdsclock <= hdmi->post_cfg->tmdsclock && hdmi->post_cfg->version) + break; + + dev_info(hdmi->dev, "%s hdmi->pre_cfg->pixclock = %lu\n",__func__, hdmi->pre_cfg->pixclock); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmdsclock = %lu\n",__func__, hdmi->pre_cfg->tmdsclock); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->prediv = %d\n",__func__, hdmi->pre_cfg->prediv); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->fbdiv = %d\n",__func__, hdmi->pre_cfg->fbdiv); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_a = %d\n",__func__, hdmi->pre_cfg->tmds_div_a); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_b = %d\n",__func__, hdmi->pre_cfg->tmds_div_b); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_c = %d\n",__func__, hdmi->pre_cfg->tmds_div_c); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_a = %d\n",__func__, hdmi->pre_cfg->pclk_div_a); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_b = %d\n",__func__, hdmi->pre_cfg->pclk_div_b); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_c = %d\n",__func__, hdmi->pre_cfg->pclk_div_c); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_d = %d\n",__func__, hdmi->pre_cfg->pclk_div_d); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->vco_div_5_en = %d\n",__func__, hdmi->pre_cfg->vco_div_5_en); + dev_info(hdmi->dev, "%s hdmi->pre_cfg->fracdiv = %d\n",__func__, hdmi->pre_cfg->fracdiv); + + + dev_info(hdmi->dev, "*******************************************************\n"); + + dev_info(hdmi->dev, "%s hdmi->post_cfg->tmdsclock = %lu\n",__func__, hdmi->post_cfg->tmdsclock); + dev_info(hdmi->dev, "%s hdmi->post_cfg->prediv = %d\n",__func__, hdmi->post_cfg->prediv); + dev_info(hdmi->dev, "%s hdmi->post_cfg->fbdiv = %d\n",__func__, hdmi->post_cfg->fbdiv); + dev_info(hdmi->dev, "%s hdmi->post_cfg->postdiv = %d\n",__func__, hdmi->post_cfg->postdiv); + dev_info(hdmi->dev, "%s hdmi->post_cfg->post_div_en = %d\n",__func__, hdmi->post_cfg->post_div_en); + dev_info(hdmi->dev, "%s hdmi->post_cfg->version = %d\n",__func__, hdmi->post_cfg->version); + + inno_hdmi_config_pll(hdmi); + //1920x1080p60 + //inno_hdmi_tx_ctrl(hdmi); + +#if 0 //pre pll + post pll configire + + /*pre-pll power down*/ + hdmi_modb(hdmi, 0x1a0, INNO_PRE_PLL_POWER_DOWN, INNO_PRE_PLL_POWER_DOWN); + + /* Configure pre-pll */ + hdmi_modb(hdmi, 0x1a0, INNO_PCLK_VCO_DIV_5_MASK, INNO_PCLK_VCO_DIV_5(hdmi->pre_cfg->vco_div_5_en)); + hdmi_writeb(hdmi, 0x1a1, INNO_PRE_PLL_PRE_DIV(hdmi->pre_cfg->prediv)); + + u32 val; + val = INNO_SPREAD_SPECTRUM_MOD_DISABLE; + if (!hdmi->pre_cfg->fracdiv) + val |= INNO_PRE_PLL_FRAC_DIV_DISABLE; + hdmi_writeb(hdmi, 0x1a2, INNO_PRE_PLL_FB_DIV_11_8(hdmi->pre_cfg->fbdiv | val)); + + hdmi_writeb(hdmi, 0x1a3, INNO_PRE_PLL_FB_DIV_7_0(hdmi->pre_cfg->fbdiv)); + + hdmi_writeb(hdmi, 0x1a5, INNO_PRE_PLL_PCLK_DIV_A(hdmi->pre_cfg->pclk_div_a) | + INNO_PRE_PLL_PCLK_DIV_B(hdmi->pre_cfg->pclk_div_b)); + + hdmi_writeb(hdmi, 0x1a6, INNO_PRE_PLL_PCLK_DIV_C(hdmi->pre_cfg->pclk_div_c) | + INNO_PRE_PLL_PCLK_DIV_D(hdmi->pre_cfg->pclk_div_d)); + + hdmi_writeb(hdmi, 0x1a4, INNO_PRE_PLL_TMDSCLK_DIV_C(hdmi->pre_cfg->tmds_div_c) | + INNO_PRE_PLL_TMDSCLK_DIV_A(hdmi->pre_cfg->tmds_div_a) | + INNO_PRE_PLL_TMDSCLK_DIV_B(hdmi->pre_cfg->tmds_div_b)); + + hdmi_writeb(hdmi, 0x1d3, INNO_PRE_PLL_FRAC_DIV_7_0(hdmi->pre_cfg->fracdiv)); + hdmi_writeb(hdmi, 0x1d2, INNO_PRE_PLL_FRAC_DIV_15_8(hdmi->pre_cfg->fracdiv)); + hdmi_writeb(hdmi, 0x1d1, INNO_PRE_PLL_FRAC_DIV_23_16(hdmi->pre_cfg->fracdiv)); + + /*pre-pll power down*/ + hdmi_modb(hdmi, 0x1a0, INNO_PRE_PLL_POWER_DOWN, 0); + + const struct phy_config *phy_cfg = inno_phy_cfg; + + for (; phy_cfg->tmdsclock != 0; phy_cfg++) + if (tmdsclock <= phy_cfg->tmdsclock) + break; + + hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POWER_DOWN, INNO_POST_PLL_POWER_DOWN); + + hdmi_writeb(hdmi, 0x1ac, INNO_POST_PLL_FB_DIV_7_0(hdmi->post_cfg->fbdiv)); + + if (hdmi->post_cfg->postdiv == 1) { + hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_REFCLK_SEL_TMDS, INNO_POST_PLL_REFCLK_SEL_TMDS); + hdmi_modb(hdmi, 0x1aa, BIT(4), INNO_POST_PLL_FB_DIV_8(hdmi->post_cfg->fbdiv)); + hdmi_modb(hdmi, 0x1ab, INNO_POST_PLL_Pre_DIV_MASK, INNO_POST_PLL_PRE_DIV(hdmi->post_cfg->prediv)); + } else { + v = (hdmi->post_cfg->postdiv / 2) - 1; + v &= INNO_POST_PLL_POST_DIV_MASK; + hdmi_modb(hdmi, 0x1ad, INNO_POST_PLL_POST_DIV_MASK, v); + hdmi_modb(hdmi, 0x1aa, BIT(4), INNO_POST_PLL_FB_DIV_8(hdmi->post_cfg->fbdiv)); + hdmi_modb(hdmi, 0x1ab, INNO_POST_PLL_Pre_DIV_MASK, INNO_POST_PLL_PRE_DIV(hdmi->post_cfg->prediv)); + hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_REFCLK_SEL_TMDS, INNO_POST_PLL_REFCLK_SEL_TMDS); + hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POST_DIV_ENABLE, INNO_POST_PLL_POST_DIV_ENABLE); + } + + for (v = 0; v < 14; v++){ + hdmi_writeb(hdmi, 0x1b5 + v, phy_cfg->regs[v]); + } + + if (phy_cfg->tmdsclock > 340000000) { + /* Set termination resistor to 100ohm */ + v = clk_get_rate(hdmi->sys_clk) / 100000; + + hdmi_writeb(hdmi, 0x1c5, INNO_TERM_RESISTOR_CALIB_SPEED_14_8(v) + | INNO_BYPASS_TERM_RESISTOR_CALIB); + + hdmi_writeb(hdmi, 0x1c6, INNO_TERM_RESISTOR_CALIB_SPEED_7_0(v)); + hdmi_writeb(hdmi, 0x1c7, INNO_TERM_RESISTOR_100); + hdmi_modb(hdmi, 0x1c5, INNO_BYPASS_TERM_RESISTOR_CALIB, 0); + } else { + hdmi_writeb(hdmi, 0x1c5, INNO_BYPASS_TERM_RESISTOR_CALIB); + + /* clk termination resistor is 50ohm (parallel resistors) */ + if (phy_cfg->tmdsclock > 165000000){ + hdmi_modb(hdmi, 0x1c8, + INNO_ESD_DETECT_MASK, + INNO_TERM_RESISTOR_200); + } + /* data termination resistor for D2, D1 and D0 is 150ohm */ + for (v = 0; v < 3; v++){ + hdmi_modb(hdmi, 0x1c9 + v, + INNO_ESD_DETECT_MASK, + INNO_TERM_RESISTOR_200); + } + } + + hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POWER_DOWN, 0); + + +#endif + return 0; + } + static int inno_hdmi_setup(struct inno_hdmi *hdmi, struct drm_display_mode *mode) { hdmi->hdmi_data.vic = drm_match_cea_mode(mode); + dev_info(hdmi->dev, "%s %d,hdmi->hdmi_data.vic = %d\n",__func__, __LINE__,hdmi->hdmi_data.vic); + + + int val; + + val = readl_relaxed(hdmi->regs + (0x1b0) * 0x04); + val |= 0x4; + writel_relaxed(val, hdmi->regs + (0x1b0) * 0x04); + writel_relaxed(0xf, hdmi->regs + (0x1cc) * 0x04); + + /*turn on pre-PLL*/ + val = readl_relaxed(hdmi->regs + (0x1a0) * 0x04); + val &= ~(0x1); + writel_relaxed(val, hdmi->regs + (0x1a0) * 0x04); + /*turn on post-PLL*/ + val = readl_relaxed(hdmi->regs + (0x1aa) * 0x04); + val &= ~(0x1); + writel_relaxed(val, hdmi->regs + (0x1aa) * 0x04); + + hdmi->tmds_rate = mode->clock * 1000; + inno_hdmi_phy_clk_set_rate(hdmi,hdmi->tmds_rate); + + dev_info(hdmi->dev, "%s %d\n",__func__, __LINE__); + + while (!(readl_relaxed(hdmi->regs + (0x1a9) * 0x04) & 0x1)) + ; + while (!(readl_relaxed(hdmi->regs + (0x1af) * 0x04) & 0x1)) + ; + + /*turn on LDO*/ + writel_relaxed(0x7, hdmi->regs + (0x1b4) * 0x04); + /*turn on serializer*/ + writel_relaxed(0x70, hdmi->regs + (0x1be) * 0x04); + inno_hdmi_tx_phy_power_down(hdmi); + /* Set HDMI Mode */ + hdmi_writeb(hdmi, 0x100,0x3); + //hdmi_writeb(hdmi, 0x8,0x00); + int value; + + /* Set detail external video timing polarity and interlace mode */ + value = v_EXTERANL_VIDEO(0); + value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? + v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0); + value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? + v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0); + value |= mode->flags & DRM_MODE_FLAG_INTERLACE ? + v_INETLACE(1) : v_INETLACE(0); + hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value); + + dev_info(hdmi->dev, "%s %d\n",__func__, __LINE__); + hdmi->hdmi_data.vic = drm_match_cea_mode(mode); + dev_info(hdmi->dev, "%s %d,hdmi->hdmi_data.vic = %d\n",__func__, __LINE__,hdmi->hdmi_data.vic); + hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB; hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB; @@ -615,35 +902,30 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, else hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; - /* Mute video and audio output */ - hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, - v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1)); + /* Mute audio output */ + hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE , + v_AUDIO_MUTE(1)); - /* Set HDMI Mode */ - hdmi_writeb(hdmi, HDMI_HDCP_CTRL, - v_HDMI_DVI(hdmi->hdmi_data.sink_is_hdmi)); - inno_hdmi_config_video_timing(hdmi, mode); + if(0 == hdmi->hdmi_data.vic) + { + inno_hdmi_config_video_timing(hdmi, mode); - inno_hdmi_config_video_csc(hdmi); + inno_hdmi_config_video_csc(hdmi); + } + dev_info(hdmi->dev, "%s %d,hdmi->hdmi_data.sink_is_hdmi = %d\n",__func__, __LINE__,hdmi->hdmi_data.sink_is_hdmi); if (hdmi->hdmi_data.sink_is_hdmi) { inno_hdmi_config_video_avi(hdmi, mode); inno_hdmi_config_video_vsi(hdmi, mode); } - /* - * When IP controller have configured to an accurate video - * timing, then the TMDS clock source would be switched to - * DCLK_LCDC, so we need to init the TMDS rate to mode pixel - * clock rate, and reconfigure the DDC clock. - */ - hdmi->tmds_rate = mode->clock * 1000; - inno_hdmi_i2c_init(hdmi); + inno_hdmi_tx_phy_power_on(hdmi); + inno_hdmi_tmds_driver_on(hdmi); - /* Unmute video and audio output */ - hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, - v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0)); + writel_relaxed(0x0, hdmi->regs + (0xce) * 0x04); + writel_relaxed(0x1, hdmi->regs + (0xce) * 0x04); + dev_info(hdmi->dev, "%s %d\n",__func__, __LINE__); return 0; } @@ -672,6 +954,14 @@ static void inno_hdmi_encoder_disable(struct drm_encoder *encoder) { struct inno_hdmi *hdmi = to_inno_hdmi(encoder); + hdmi_modb(hdmi, 0x1b2, 0xf, 0); + hdmi_modb(hdmi, 0x1be, 0xf, 0); + hdmi_modb(hdmi, 0x1b4, 0xf, 0); + hdmi_modb(hdmi, 0x1a0, 1, 1); + hdmi_modb(hdmi, 0x1aa, 1, 1); + hdmi_modb(hdmi, 0x1cc, 0x0f, 0); + hdmi_modb(hdmi, 0x1b0, 1<<2, 0); + inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR); } @@ -733,11 +1023,119 @@ static int inno_hdmi_connector_get_modes(struct drm_connector *connector) return ret; } +static const struct dw_hdmi_mpll_config starfive_mpll_cfg[] = { + { + 25200000, { + { 0x00b3, 0x0000}, + { 0x2153, 0x0000}, + { 0x40f3, 0x0000} + }, + }, { + 27000000, { + { 0x00b3, 0x0000}, + { 0x2153, 0x0000}, + { 0x40f3, 0x0000} + }, + }, { + 36000000, { + { 0x00b3, 0x0000}, + { 0x2153, 0x0000}, + { 0x40f3, 0x0000} + }, + }, { + 40000000, { + { 0x00b3, 0x0000}, + { 0x2153, 0x0000}, + { 0x40f3, 0x0000} + }, + }, { + 54000000, { + { 0x0072, 0x0001}, + { 0x2142, 0x0001}, + { 0x40a2, 0x0001}, + }, + }, { + 65000000, { + { 0x0072, 0x0001}, + { 0x2142, 0x0001}, + { 0x40a2, 0x0001}, + }, + }, { + 66000000, { + { 0x013e, 0x0003}, + { 0x217e, 0x0002}, + { 0x4061, 0x0002} + }, + }, { + 74250000, { + { 0x0072, 0x0001}, + { 0x2145, 0x0002}, + { 0x4061, 0x0002} + }, + }, { + 83500000, { + { 0x0072, 0x0001}, + }, + }, { + 108000000, { + { 0x0051, 0x0002}, + { 0x2145, 0x0002}, + { 0x4061, 0x0002} + }, + }, { + 106500000, { + { 0x0051, 0x0002}, + { 0x2145, 0x0002}, + { 0x4061, 0x0002} + }, + }, { + 146250000, { + { 0x0051, 0x0002}, + { 0x2145, 0x0002}, + { 0x4061, 0x0002} + }, + }, { + 148500000, { + { 0x0051, 0x0003}, + { 0x214c, 0x0003}, + { 0x4064, 0x0003} + }, + }, { + ~0UL, { + { 0x00a0, 0x000a }, + { 0x2001, 0x000f }, + { 0x4002, 0x000f }, + }, + } +}; + static enum drm_mode_status inno_hdmi_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - return MODE_OK; +#if 0 + const struct dw_hdmi_mpll_config *mpll_cfg = starfive_mpll_cfg; + int pclk = mode->clock * 1000; + bool valid = false; + int i; + + for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { + if (pclk == mpll_cfg[i].mpixelclock) { + valid = true; + break; + } + } + + return (valid) ? MODE_OK : MODE_BAD; +#endif + u32 vic = drm_match_cea_mode(mode); + + if (vic >= 1) + return MODE_OK; + else + return MODE_BAD; + + //return MODE_OK; } static int @@ -1131,21 +1529,8 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, } udelay(100); -//20220531 clk rst interface support -#if 1 ret = inno_hdmi_get_clk_rst(dev, hdmi); - //if (ret) { - // dev_err(dev, "failed to get clock or reset\n"); - // return ret; - //} ret = inno_hdmi_en_clk_deas_rst(dev, hdmi); - //if (ret) { - // dev_err(dev, "failed to enable clock or deassert reset\n"); - // return ret; - //} -#endif -//20220531 clk rst interface support - irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -1218,15 +1603,9 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, clk_disable_unprepare(hdmi->mclk); clk_disable_unprepare(hdmi->bclk); - //pmic turn off - #if 1 regulator_disable(hdmi->hdmi_1p8); udelay(100); regulator_disable(hdmi->hdmi_0p9); - #endif - //pmic turn off - -// clk_disable_unprepare(hdmi->pclk); } static const struct component_ops inno_hdmi_ops = { diff --git a/drivers/gpu/drm/verisilicon/inno_hdmi.h b/drivers/gpu/drm/verisilicon/inno_hdmi.h old mode 100644 new mode 100755 index d463f13..1799553 --- a/drivers/gpu/drm/verisilicon/inno_hdmi.h +++ b/drivers/gpu/drm/verisilicon/inno_hdmi.h @@ -374,4 +374,175 @@ typedef enum { } vic_code_t; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l))) + + /* REG: 0x1a0 */ +#define INNO_PCLK_VCO_DIV_5_MASK BIT(1) +#define INNO_PCLK_VCO_DIV_5(x) UPDATE(x, 1, 1) +#define INNO_PRE_PLL_POWER_DOWN BIT(0) + + /* REG: 0x1a1 */ +#define INNO_PRE_PLL_PRE_DIV_MASK GENMASK(5, 0) +#define INNO_PRE_PLL_PRE_DIV(x) UPDATE(x, 5, 0) + + + /* REG: 0xa2 */ + /* unset means center spread */ +#define INNO_SPREAD_SPECTRUM_MOD_DOWN BIT(7) +#define INNO_SPREAD_SPECTRUM_MOD_DISABLE BIT(6) +#define INNO_PRE_PLL_FRAC_DIV_DISABLE UPDATE(3, 5, 4) +#define INNO_PRE_PLL_FB_DIV_11_8_MASK GENMASK(3, 0) +#define INNO_PRE_PLL_FB_DIV_11_8(x) UPDATE((x) >> 8, 3, 0) + + /* REG: 0xa3 */ +#define INNO_PRE_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0) + + /* REG: 0xa4*/ +#define INNO_PRE_PLL_TMDSCLK_DIV_C_MASK GENMASK(1, 0) +#define INNO_PRE_PLL_TMDSCLK_DIV_C(x) UPDATE(x, 1, 0) +#define INNO_PRE_PLL_TMDSCLK_DIV_B_MASK GENMASK(3, 2) +#define INNO_PRE_PLL_TMDSCLK_DIV_B(x) UPDATE(x, 3, 2) +#define INNO_PRE_PLL_TMDSCLK_DIV_A_MASK GENMASK(5, 4) +#define INNO_PRE_PLL_TMDSCLK_DIV_A(x) UPDATE(x, 5, 4) + /* REG: 0xa5 */ +#define INNO_PRE_PLL_PCLK_DIV_B_SHIFT 5 +#define INNO_PRE_PLL_PCLK_DIV_B_MASK GENMASK(6, 5) +#define INNO_PRE_PLL_PCLK_DIV_B(x) UPDATE(x, 6, 5) +#define INNO_PRE_PLL_PCLK_DIV_A_MASK GENMASK(4, 0) +#define INNO_PRE_PLL_PCLK_DIV_A(x) UPDATE(x, 4, 0) + + /* REG: 0xa6 */ +#define INNO_PRE_PLL_PCLK_DIV_C_SHIFT 5 +#define INNO_PRE_PLL_PCLK_DIV_C_MASK GENMASK(6, 5) +#define INNO_PRE_PLL_PCLK_DIV_C(x) UPDATE(x, 6, 5) +#define INNO_PRE_PLL_PCLK_DIV_D_MASK GENMASK(4, 0) +#define INNO_PRE_PLL_PCLK_DIV_D(x) UPDATE(x, 4, 0) + + /* REG: 0xd1 */ +#define INNO_PRE_PLL_FRAC_DIV_23_16(x) UPDATE((x) >> 16, 7, 0) + /* REG: 0xd2 */ +#define INNO_PRE_PLL_FRAC_DIV_15_8(x) UPDATE((x) >> 8, 7, 0) + /* REG: 0xd3 */ +#define INNO_PRE_PLL_FRAC_DIV_7_0(x) UPDATE(x, 7, 0) + + /* REG: 0x1aa */ +#define INNO_POST_PLL_POST_DIV_ENABLE GENMASK(3, 2) +#define INNO_POST_PLL_REFCLK_SEL_TMDS BIT(1) +#define INNO_POST_PLL_POWER_DOWN BIT(0) +#define INNO_POST_PLL_FB_DIV_8(x) UPDATE(((x) >> 8) <<4 , 4, 4) + + /* REG:0x1ab */ +#define INNO_POST_PLL_Pre_DIV_MASK GENMASK(5, 0) +#define INNO_POST_PLL_PRE_DIV(x) UPDATE(x, 5, 0) + /* REG: 0x1ac */ +#define INNO_POST_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0) + /* REG: 0x1ad */ +#define INNO_POST_PLL_POST_DIV_MASK GENMASK(2, 0) +#define INNO_POST_PLL_POST_DIV_2 0x0 +#define INNO_POST_PLL_POST_DIV_4 0x1 +#define INNO_POST_PLL_POST_DIV_8 0x3 + /* REG: 0x1af */ +#define INNO_POST_PLL_LOCK_STATUS BIT(0) + /* REG: 0x1b0 */ +#define INNO_BANDGAP_ENABLE BIT(2) + /* REG: 0x1b2 */ +#define INNO_TMDS_CLK_DRIVER_EN BIT(3) +#define INNO_TMDS_D2_DRIVER_EN BIT(2) +#define INNO_TMDS_D1_DRIVER_EN BIT(1) +#define INNO_TMDS_D0_DRIVER_EN BIT(0) +#define INNO_TMDS_DRIVER_ENABLE (INNO_TMDS_CLK_DRIVER_EN | \ + INNO_TMDS_D2_DRIVER_EN | \ + INNO_TMDS_D1_DRIVER_EN | \ + INNO_TMDS_D0_DRIVER_EN) + /* REG:0x1c5 */ +#define INNO_BYPASS_TERM_RESISTOR_CALIB BIT(7) +#define INNO_TERM_RESISTOR_CALIB_SPEED_14_8(x) UPDATE((x) >> 8, 6, 0) + /* REG:0x1c6 */ +#define INNO_TERM_RESISTOR_CALIB_SPEED_7_0(x) UPDATE(x, 7, 0) + /* REG:0x1c7 */ +#define INNO_TERM_RESISTOR_100 UPDATE(0, 2, 1) +#define INNO_TERM_RESISTOR_125 UPDATE(1, 2, 1) +#define INNO_TERM_RESISTOR_150 UPDATE(2, 2, 1) +#define INNO_TERM_RESISTOR_200 UPDATE(3, 2, 1) + /* REG 0x1c8 - 0x1cb */ +#define INNO_ESD_DETECT_MASK GENMASK(5, 0) +#define INNO_ESD_DETECT_340MV (0x0 << 6) +#define INNO_ESD_DETECT_280MV (0x1 << 6) +#define INNO_ESD_DETECT_260MV (0x2 << 6) +#define INNO_ESD_DETECT_240MV (0x3 << 6) + /* resistors can be used in parallel */ +#define INNO_TMDS_TERM_RESIST_MASK GENMASK(5, 0) +#define INNO_TMDS_TERM_RESIST_125 BIT(5) +#define INNO_TMDS_TERM_RESIST_250 BIT(4) +#define INNO_TMDS_TERM_RESIST_500 BIT(3) +#define INNO_TMDS_TERM_RESIST_1000 BIT(2) +#define INNO_TMDS_TERM_RESIST_2000 BIT(1) +#define INNO_TMDS_TERM_RESIST_4000 BIT(0) + +struct pre_pll_config { + unsigned long pixclock; + unsigned long tmdsclock; + u8 prediv; + u16 fbdiv; + u8 tmds_div_a; + u8 tmds_div_b; + u8 tmds_div_c; + u8 pclk_div_a; + u8 pclk_div_b; + u8 pclk_div_c; + u8 pclk_div_d; + u8 vco_div_5_en; + u32 fracdiv; +}; + +struct post_pll_config { + unsigned long tmdsclock; + u8 prediv; + u16 fbdiv; + u8 postdiv; + u8 post_div_en; + u8 version; +}; + +struct phy_config { + unsigned long tmdsclock; + u8 regs[14]; +}; + +typedef struct register_value { + u16 reg; + u8 value; +} reg_value_t; + #endif /* __INNO_HDMI_H__ */ diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c old mode 100644 new mode 100755 index 3e26baa..8c6a7a7 --- a/drivers/gpu/drm/verisilicon/vs_dc.c +++ b/drivers/gpu/drm/verisilicon/vs_dc.c @@ -30,6 +30,11 @@ #include #endif +//syscon panel +#include +#include +//syscon panel + static inline void update_format(u32 format, u64 mod, struct dc_hw_fb *fb) { u8 f = FORMAT_A8R8G8B8; @@ -332,10 +337,7 @@ static int vs_dc_get_clock(struct device *dev, struct vs_dc *dc) } return ret; } -//noc bus clk get - -//noc bus clk enable static int vs_dc_clock_enable(struct device *dev, struct vs_dc *dc) { int ret; @@ -590,16 +592,16 @@ static int vs_dc_vouttop_resets_assert(struct device *dev, struct vs_dc *dc) static int vs_dc_dc8200_get_clock(struct device *dev, struct vs_dc *dc) { int ret; - dc->dc8200_pix0 = devm_clk_get(dev, "pix_clk"); - if (IS_ERR(dc->dc8200_pix0)) { - dev_err(dev, "---dc8200_pix0 get error\n"); - return PTR_ERR(dc->dc8200_pix0); + dc->dc8200_clk_pix0 = devm_clk_get(dev, "pix_clk"); + if (IS_ERR(dc->dc8200_clk_pix0)) { + dev_err(dev, "---dc8200_clk_pix0 get error\n"); + return PTR_ERR(dc->dc8200_clk_pix0); } - dc->dc8200_pix1 = devm_clk_get(dev, "vout_pix1"); - if (IS_ERR(dc->dc8200_pix1)) { - dev_err(dev, "---dc8200_pix1 get error\n"); - return PTR_ERR(dc->dc8200_pix1); + dc->dc8200_clk_pix1 = devm_clk_get(dev, "vout_pix1"); + if (IS_ERR(dc->dc8200_clk_pix1)) { + dev_err(dev, "---dc8200_clk_pix1 get error\n"); + return PTR_ERR(dc->dc8200_clk_pix1); } dc->dc8200_axi = devm_clk_get(dev, "axi_clk"); @@ -626,14 +628,14 @@ static int vs_dc_dc8200_clock_enable(struct device *dev, struct vs_dc *dc) { int ret; /*clk_prepare_enable(dc->sys_clk);*/ - ret = clk_prepare_enable(dc->dc8200_pix0); + ret = clk_prepare_enable(dc->dc8200_clk_pix0); if (ret) { - dev_err(dev, "failed to prepare/enable dc8200_pix0\n"); + dev_err(dev, "failed to prepare/enable dc8200_clk_pix0\n"); return ret; } - ret = clk_prepare_enable(dc->dc8200_pix1); + ret = clk_prepare_enable(dc->dc8200_clk_pix1); if (ret) { - dev_err(dev, "failed to prepare/enable dc8200_pix1\n"); + dev_err(dev, "failed to prepare/enable dc8200_clk_pix1\n"); return ret; } ret = clk_prepare_enable(dc->dc8200_axi); @@ -657,8 +659,8 @@ static int vs_dc_dc8200_clock_enable(struct device *dev, struct vs_dc *dc) static void vs_dc_dc8200_clock_disable(struct vs_dc *dc) { - clk_disable_unprepare(dc->dc8200_pix0); - clk_disable_unprepare(dc->dc8200_pix1); + clk_disable_unprepare(dc->dc8200_clk_pix0); + clk_disable_unprepare(dc->dc8200_clk_pix1); clk_disable_unprepare(dc->dc8200_axi); clk_disable_unprepare(dc->dc8200_core); clk_disable_unprepare(dc->dc8200_ahb); @@ -731,7 +733,6 @@ static int vs_dc_dc8200_resets_assert(struct device *dev, struct vs_dc *dc) static int dc_vout_clk_rst_init(struct device *dev, struct vs_dc *dc) { int ret; - #if 1 //noc bus ret = vs_dc_get_clock(dev, dc); if (ret) { dev_err(dev, "failed to get clock\n"); @@ -752,9 +753,7 @@ static int dc_vout_clk_rst_init(struct device *dev, struct vs_dc *dc) dev_err(dev, "failed to deassert reset\n"); return ret; } - #endif - #if 1 //vout top ret = vs_dc_vouttop_get_clock(dev, dc); if (ret) { dev_err(dev, "failed to get clock\n"); @@ -775,9 +774,7 @@ static int dc_vout_clk_rst_init(struct device *dev, struct vs_dc *dc) dev_err(dev, "failed to deassert reset\n"); return ret; } - #endif - #if 1 //dc8200 ret = vs_dc_dc8200_get_clock(dev, dc); if (ret) { dev_err(dev, "failed to get clock\n"); @@ -798,40 +795,73 @@ static int dc_vout_clk_rst_init(struct device *dev, struct vs_dc *dc) dev_err(dev, "failed to deassert reset\n"); return ret; } - #endif return ret; } -int sys_vout_mux_config(void) + +static int syscon_panel_parse_dt(struct device *dev) { - #ifdef CONFIG_DRM_I2C_NXP_TDA998X//tda998x-rgb2hdmi - SET_U0_LCD_DATA_MAPPING_DPI_DP_SEL(0);//DC8200_INTERFACE_DPI - SET_U0_LCD_DATA_MAPPING_DP_RGB_FMT(0);//0-RGB888 - SET_U0_DISPLAY_PANEL_MUX_PANEL_SEL(0);//panel 0 - #else - if(1){ - SET_U0_HDMI_DATA_MAPPING_DPI_DP_SEL(0); - SET_U0_HDMI_DATA_MAPPING_DPI_BIT_DEPTH(0); - SET_U0_HDMI_DATA_MAPPING_DP_BIT_DEPTH(0); - SET_U0_HDMI_DATA_MAPPING_DP_YUV_MODE(0); - SET_U2_DISPLAY_PANEL_MUX_PANEL_SEL(0); - - } - #endif - return 0; + struct vs_dc *dc = dev_get_drvdata(dev); + int ret = 0; + + dc->dss_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, + "verisilicon,dss-syscon"); + + if (IS_ERR(dc->dss_regmap)) { + if (PTR_ERR(dc->dss_regmap) != -ENODEV) { + dev_err(dev, "failed to get dss-syscon\n"); + ret = PTR_ERR(dc->dss_regmap); + goto err; + } + dc->dss_regmap = NULL; + goto err; + } + +err: + return ret; } -int sys_dispctrl_clk(void) +int sys_dispctrl_clk_standard(struct vs_dc *dc, struct device *dev) { - #ifdef CONFIG_DRM_I2C_NXP_TDA998X//tda998x-rgb2hdmi - _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX1_SOURCE_CLK_HDMITX0_PIXELCLK_; - _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_HDMITX0_PIXELCLK_; - //_ENABLE_CLOCK_CLK_DOM_VOUT_TOP_LCD_CLK_;//disabled standard - #else - _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_HDMITX0_PIXELCLK_; - //_SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_DC8200_PIX0_; - #endif +#ifdef CONFIG_DRM_I2C_NXP_TDA998X + dc->dc8200_clk_pix1 = devm_clk_get(dev, "vout_pix1"); + if (IS_ERR(dc->dc8200_clk_pix1)) { + dev_err(dev, "---dc8200_clk_pix1 get error\n"); + return PTR_ERR(dc->dc8200_clk_pix1); + } + + dc->hdmitx0_pixelclk = devm_clk_get(dev, "hdmitx0_pixelclk"); + if (IS_ERR(dc->hdmitx0_pixelclk)) { + dev_err(dev, "---hdmitx0_pixelclk get error\n"); + return PTR_ERR(dc->hdmitx0_pixelclk); + } + + dc->dc8200_clk_pix0 = devm_clk_get(dev, "pix_clk"); + if (IS_ERR(dc->dc8200_clk_pix0)) { + dev_err(dev, "---dc8200_clk_pix0 get error\n"); + return PTR_ERR(dc->dc8200_clk_pix0); + } + + clk_set_parent( dc->dc8200_clk_pix1, dc->hdmitx0_pixelclk ); + clk_set_parent( dc->dc8200_clk_pix0, dc->hdmitx0_pixelclk ); + +#else + //_SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_HDMITX0_PIXELCLK_; + dc->dc8200_clk_pix0 = devm_clk_get(dev, "pix_clk"); //dc8200_clk_pix0 + if (IS_ERR(dc->dc8200_clk_pix0)) { + dev_err(dev, "---dc8200_clk_pix0 get error\n"); + return PTR_ERR(dc->dc8200_clk_pix0); + } + + dc->hdmitx0_pixelclk = devm_clk_get(dev, "hdmitx0_pixelclk");//hdmitx0_pixelclk + if (IS_ERR(dc->hdmitx0_pixelclk)) { + dev_err(dev, "---hdmitx0_pixelclk get error\n"); + return PTR_ERR(dc->hdmitx0_pixelclk); + } + clk_set_parent( dc->dc8200_clk_pix0, dc->hdmitx0_pixelclk );//parent,child + +#endif return 0; } @@ -841,11 +871,7 @@ int drv_config_dc_4_dsi(struct vs_dc *dc, struct device *dev)//for dc_dsi config int ret; dev_info(dev, "====> %s, %d.\n", __func__, __LINE__); - /*---------------------mux config------------*/ - SET_U0_DSITX_DATA_MAPPING_DPI_DP_SEL(0); - //SET_U0_DSITX_DATA_MAPPING_DP_MODE(vout_sys->vout_dsitx.dp_color_mode); - SET_U1_DISPLAY_PANEL_MUX_PANEL_SEL(0); - //_ENABLE_CLOCK_CLK_DOM_VOUT_TOP_LCD_CLK_; + ret = clk_prepare_enable(dc->vout_top_lcd); if (ret) { dev_err(dev, "failed to prepare/enable vout_top_lcd\n"); @@ -856,15 +882,6 @@ int drv_config_dc_4_dsi(struct vs_dc *dc, struct device *dev)//for dc_dsi config return 0; } -int sys_dispctrl_init(void) -{ - sys_vout_mux_config(); - sys_dispctrl_clk(); - - mdelay(1); - return 0; -} - static void dc_deinit(struct device *dev) { struct vs_dc *dc = dev_get_drvdata(dev); @@ -890,20 +907,26 @@ static int dc_init(struct device *dev) dc->first_frame = true; - //power_set(dev, 1); + ret = syscon_panel_parse_dt(dev); + if (ret){ + dev_err(dev,"syscon_panel_parse_dt failed\n"); + return ret; + } starfive_power_domain_set(POWER_DOMAIN_VOUT, 1); //ret = plda_clk_rst_init(dev); ret = dc_vout_clk_rst_init(dev, dc); - ret = sys_dispctrl_init(); - if (ret < 0) { - dev_err(dev, "failed to init vout clk reset: %d\n", ret); - return ret; - } + #ifdef CONFIG_DRM_I2C_NXP_TDA998X//tda998x-rgb2hdmi + regmap_update_bits(dc->dss_regmap, 0x4, BIT(20), 1<<20); + #endif + + ret = sys_dispctrl_clk_standard(dc, dev); + #ifdef CONFIG_STARFIVE_DSI dev_info(dev, "dc mipi channel\n"); + regmap_update_bits(dc->dss_regmap, 0x8, BIT(3), 1<<3); dc->vout_src = devm_clk_get(dev, "vout_src"); if (IS_ERR(dc->vout_src)){ dev_err(dev,"failed to get dc->vout_src\n"); @@ -914,6 +937,15 @@ static int dc_init(struct device *dev) dev_err(dev,"failed to get dc->vout_top_lcd\n"); return PTR_ERR(dc->vout_top_lcd); } + #if 1 //parent for dc8200_clk_pix0 !! + dc->dc8200_pix0 = devm_clk_get(dev, "dc8200_pix0"); //dc8200_pix0 + if (IS_ERR(dc->dc8200_pix0)) { + dev_err(dev, "---dc8200_pix0 get error\n"); + return PTR_ERR(dc->dc8200_pix0); + } + #endif + //_SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_DC8200_PIX0_; + clk_set_parent( dc->dc8200_clk_pix0, dc->dc8200_pix0 );//child,parent ret = drv_config_dc_4_dsi(dc,dev); if (ret < 0) { dev_err(dev, "failed to drv_config_dc_4_dsi: %d\n", ret); @@ -923,19 +955,22 @@ static int dc_init(struct device *dev) #ifdef CONFIG_DRM_I2C_NXP_TDA998X _ENABLE_CLOCK_CLK_DOM_VOUT_TOP_LCD_CLK_; - /* + #if 0 //to do fix dev_info(dev, "dc rgb2hdmi channel\n"); dc->vout_top_lcd = devm_clk_get(dev, "vout_top_lcd"); if (IS_ERR(dc->vout_top_lcd)){ dev_err(dev,"failed to get dc->vout_top_lcd\n"); return PTR_ERR(dc->vout_top_lcd); } + + clk_set_parent( dc->vout_top_lcd, dc->dc8200_clk_pix1); + ret = clk_prepare_enable(dc->vout_top_lcd); if (ret) { dev_err(dev, "failed to prepare/enable vout_top_lcd\n"); return ret; } - */ + #endif #endif printk("====> %s, %d.\n", __func__, __LINE__); @@ -970,10 +1005,14 @@ static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc) struct vs_crtc_state *crtc_state = to_vs_crtc_state(crtc->state); struct drm_display_mode *mode = &crtc->state->adjusted_mode; struct dc_hw_display display; +#ifdef CONFIG_STARFIVE_DSI//7110 mipi + #if 0 uint32_t vout_clock; uint32_t div; uint32_t div_new; const uint32_t wanted_pxclk = mode->clock * 1000; + #endif +#endif display.bus_format = crtc_state->output_fmt; display.h_active = mode->hdisplay; @@ -1003,47 +1042,8 @@ static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc) display.enable = true; -#if 1 - ;//printk("====> %s, %d--pix_clk.\n", __func__, __LINE__); -#else - //used for div clock - if (dc->pix_clk_rate != mode->clock) { - printk("====> %s, %d--pix_clk.mode->clock = %d\n", __func__, __LINE__,mode->clock); - u32 div = _GET_CLOCK_DIVIDE_STATUS_CLK_DC8200_PIX0_; - printk("====> %s, %d--pix_clk.div = %d\n", __func__, __LINE__,div); - - //148500 - div = 1228800/mode->clock; - //148500 - printk("====> %s, %d--pix_clk.div = %d\n", __func__, __LINE__,div); - - _DIVIDE_CLOCK_CLK_DC8200_PIX0_(div); - _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_DC8200_PIX0_; - _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX1_SOURCE_CLK_DC8200_PIX0_; - - _SWITCH_CLOCK_CLK_DOM_VOUT_TOP_LCD_CLK_SOURCE_CLK_U0_DC8200_CLK_PIX0_OUT_; - - //clk_set_rate(dc->pix_clk, mode->clock * 1000); - dc->pix_clk_rate = mode->clock; - } -#endif - -#ifdef CONFIG_STARFIVE_DSI//7110 mipi - /*-----------------div freq clk sys_dispctrl_clk()----------*/ - //const uint32_t wanted_pxclk = 20144262;//dpi->pixelclock; - //wanted_pxclk = mode->clock * 1000; - dev_info(dev, "wanted_pxclk = %d\n",wanted_pxclk); - //uint32_t vout_clock = 614400000; - vout_clock = clk_get_rate(dc->vout_src); - dev_info(dev, "vout_clock = %d\n", vout_clock); - div = _GET_CLOCK_DIVIDE_STATUS_CLK_DC8200_PIX0_; - div_new = vout_clock / wanted_pxclk; - if (div != div_new) { - div = div_new; - _DIVIDE_CLOCK_CLK_DC8200_PIX0_(div); - _SWITCH_CLOCK_CLK_U0_DC8200_CLK_PIX0_SOURCE_CLK_DC8200_PIX0_; - } - /*-----------------div freq clk sys_dispctrl_clk()----------*/ +#ifdef CONFIG_STARFIVE_DSI// + clk_set_rate(dc->dc8200_pix0, 20144263);//round up, 20144262+1 #endif if (crtc_state->encoder_type == DRM_MODE_ENCODER_DSI) diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h old mode 100644 new mode 100755 index a645c3e..e07bcfc --- a/drivers/gpu/drm/verisilicon/vs_dc.h +++ b/drivers/gpu/drm/verisilicon/vs_dc.h @@ -54,54 +54,47 @@ struct vs_dc { const struct vs_dc_funcs *funcs; -//noc bus clk struct clk *cpu_axi; struct clk *axicfg0_axi; struct clk *disp_axi; struct clk *stg_axi; -//noc bus clk -//noc bus rst + struct reset_control *cpu_axi_n; struct reset_control *axicfg0_axi_n; struct reset_control *apb_bus_n; struct reset_control *disp_axi_n; struct reset_control *stg_axi_n; -//noc bus rst -//vout top clk struct clk *vout_src; struct clk *vout_axi; struct clk *ahb1; struct clk *vout_ahb; struct clk *hdmitx0_mclk; struct clk *bclk_mst; -//vout top clk -//vout top rst + struct reset_control *rstn_vout_src; -//vout top rst -//dc8200 clk - struct clk *dc8200_pix0; - struct clk *dc8200_pix1; + struct clk *dc8200_clk_pix0; + struct clk *dc8200_clk_pix1; struct clk *dc8200_axi; struct clk *dc8200_core; struct clk *dc8200_ahb; -//dc8200 clk -//dc8200 rst + struct reset_control *rstn_dc8200_axi; struct reset_control *rstn_dc8200_core; struct reset_control *rstn_dc8200_ahb; -//dc8200 rst -//7110 mp -struct clk *vout_top_axi; -struct clk *vout_top_lcd; -//7110 mp + struct clk *vout_top_axi; + struct clk *vout_top_lcd; + + struct clk *hdmitx0_pixelclk; + struct clk *dc8200_pix0; + + struct regmap *dss_regmap; }; extern struct platform_driver dc_platform_driver; -//extern struct platform_driver simple_encoder_driver; extern struct platform_driver starfive_dsi_platform_driver; extern int init_seeed_panel(void); extern void exit_seeed_panel(void); diff --git a/drivers/gpu/drm/verisilicon/vs_drv.c b/drivers/gpu/drm/verisilicon/vs_drv.c old mode 100644 new mode 100755 index 0508da6..84c2616 --- a/drivers/gpu/drm/verisilicon/vs_drv.c +++ b/drivers/gpu/drm/verisilicon/vs_drv.c @@ -468,7 +468,6 @@ static int __init vs_drm_init(void) { int ret; - printk("%s:%d\n", __func__, __LINE__); ret = platform_register_drivers(drm_sub_drivers, NUM_DRM_DRIVERS); if (ret) return ret; diff --git a/drivers/gpu/drm/verisilicon/vs_simple_enc.c b/drivers/gpu/drm/verisilicon/vs_simple_enc.c old mode 100644 new mode 100755 index 31672b0..48654ea --- a/drivers/gpu/drm/verisilicon/vs_simple_enc.c +++ b/drivers/gpu/drm/verisilicon/vs_simple_enc.c @@ -38,6 +38,7 @@ static inline struct simple_encoder *to_simple_encoder(struct drm_encoder *enc) return container_of(enc, struct simple_encoder, encoder); } +#if 0 static int encoder_parse_dt(struct device *dev) { struct simple_encoder *simple = dev_get_drvdata(dev); @@ -103,6 +104,7 @@ err_free_masks: err: return ret; } +#endif #define DOM_VOUT_SYSCON_8 0x8U #define U0_LCD_DATA_MAPPING_DPI_DP_SEL_SHIFT 0x2U @@ -116,6 +118,8 @@ void encoder_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct simple_encoder *simple = to_simple_encoder(encoder); + printk("encoder_atomic_enable\n"); + #if 0 struct dss_data *data = simple->dss_regdatas; int crtc_id; @@ -130,6 +134,7 @@ void encoder_atomic_enable(struct drm_encoder *encoder, regmap_update_bits(simple->dss_regmap, DOM_VOUT_SYSCON_8, U0_LCD_DATA_MAPPING_DPI_DP_SEL_MASK, 0); regmap_update_bits(simple->dss_regmap, DOM_VOUT_SYSCON_4, U0_DISPLAY_PANEL_MUX_PANEL_SEL_MASK, 0); + #endif } int encoder_atomic_check(struct drm_encoder *encoder, @@ -221,6 +226,7 @@ static int encoder_bind(struct device *dev, struct device *master, void *data) encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, dev->of_node); + encoder->possible_crtcs = 3; /* output port is port1*/ @@ -289,11 +295,11 @@ static int encoder_probe(struct platform_device *pdev) simple->dev = dev; dev_set_drvdata(dev, simple); - +#if 0 ret = encoder_parse_dt(dev); if (ret) return ret; - +#endif return component_add(dev, &encoder_component_ops); }