diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 95550a983898..ca8cb84bac5f 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -165,6 +165,5 @@ config ROCKCHIP_DW_HDCP2 Designware HDCP2 Controller. source "drivers/gpu/drm/rockchip/rk618/Kconfig" -source "drivers/gpu/drm/rockchip/rk628/Kconfig" endif diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index 7aa90fa2002c..a211c295664b 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -31,4 +31,3 @@ rockchipdrm-$(CONFIG_DRM_ROCKCHIP_VVOP) += rockchip_drm_vvop.o obj-$(CONFIG_ROCKCHIP_DW_HDCP2) += dw_hdcp2.o obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o obj-$(CONFIG_DRM_ROCKCHIP_RK618) += rk618/ -obj-$(CONFIG_DRM_ROCKCHIP_RK628) += rk628/ diff --git a/drivers/gpu/drm/rockchip/rk628/Kconfig b/drivers/gpu/drm/rockchip/rk628/Kconfig deleted file mode 100644 index 41e1fbbe1e61..000000000000 --- a/drivers/gpu/drm/rockchip/rk628/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -config DRM_ROCKCHIP_RK628 - tristate "Rockchip RK628 display bridge driver" - depends on DRM_ROCKCHIP - depends on MFD_RK628 - help - Rockchip RK628 display bridge chips driver. diff --git a/drivers/gpu/drm/rockchip/rk628/Makefile b/drivers/gpu/drm/rockchip/rk628/Makefile deleted file mode 100644 index 76d768d29776..000000000000 --- a/drivers/gpu/drm/rockchip/rk628/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the Rockchip RK628 display bridge driver. -# - -obj-$(CONFIG_DRM_ROCKCHIP_RK628) += rk628_combrxphy.o \ - rk628_combtxphy.o \ - rk628_dsi.o \ - rk628_gvi.o \ - rk628_lvds.o \ - rk628_post_process.o \ - rk628_rgb.o \ - rk628_hdmi.o \ - rk628_hdmirx.o diff --git a/drivers/gpu/drm/rockchip/rk628/rk628_combrxphy.c b/drivers/gpu/drm/rockchip/rk628/rk628_combrxphy.c deleted file mode 100644 index a83eeeaf935f..000000000000 --- a/drivers/gpu/drm/rockchip/rk628/rk628_combrxphy.c +++ /dev/null @@ -1,1030 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2020 Rockchip Electronics Co. Ltd. - * - * Author: Algea Cao - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct rk628_combrxphy { - struct device *dev; - struct rk628 *parent; - struct regmap *regmap; - struct clk *pclk; - struct reset_control *rstc; - bool is_cable_mode; -}; - -#define REG(x) ((x) + 0x10000) -#define COMBRXPHY_MAX_REGISTER REG(0x6790) - -#define MAX_ROUND 6 -#define MAX_DATA_NUM 16 -#define MAX_CHANNEL 3 -#define CLK_DET_TRY_TIMES 10 -#define CLK_STABLE_LOOP_CNT 10 -#define CLK_STABLE_THRESHOLD 6 - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "debug level (0-1)"); - -static void rk628_combrxphy_set_data_of_round(u32 *data, u32 *data_in) -{ - if ((data != NULL) && (data_in != NULL)) { - data_in[0] = data[0]; - data_in[1] = data[7]; - data_in[2] = data[13]; - data_in[3] = data[14]; - data_in[4] = data[15]; - data_in[5] = data[1]; - data_in[6] = data[2]; - data_in[7] = data[3]; - data_in[8] = data[4]; - data_in[9] = data[5]; - data_in[10] = data[6]; - data_in[11] = data[8]; - data_in[12] = data[9]; - data_in[13] = data[10]; - data_in[14] = data[11]; - data_in[15] = data[12]; - } -} - -static void -rk628_combrxphy_max_zero_of_round(struct rk628_combrxphy *combrxphy, - u32 *data_in, u32 *max_zero, u32 *max_val, - int n, int ch) -{ - u32 i; - u32 cnt = 0; - u32 max_cnt = 0; - u32 max_v = 0; - - if (debug > 0) { - dev_info(combrxphy->dev, - "%s channel:%d, round:%d ====\n", __func__, ch, n); - print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_NONE, 32, 4, - data_in, MAX_DATA_NUM * sizeof(u32), false); - } - - for (i = 0; i < MAX_DATA_NUM; i++) { - if (max_v < data_in[i]) - max_v = data_in[i]; - } - - for (i = 0; i < MAX_DATA_NUM; i++) { - if (data_in[i] == 0) - cnt = cnt + 200; - else if ((data_in[i] > 0) && (data_in[i] < 100)) - cnt = cnt + 100 - data_in[i]; - } - max_cnt = (cnt >= 3200) ? 0 : cnt; - - max_zero[n] = max_cnt; - max_val[n] = max_v; - dev_dbg(combrxphy->dev, - "channel:%d, round:%d, max_zero_cnt:%d, max_val:%#x", - ch, n, max_zero[n], max_val[n]); -} - -static int -rk628_combrxphy_chose_round_for_ch(struct rk628_combrxphy *combrxphy, - u32 *rd_max_zero, - u32 *rd_max_val, int ch) -{ - int i, rd = 0; - u32 max = 0; - u32 max_v = 0; - - if (debug > 0) { - dev_info(combrxphy->dev, - "%s max cnt of channel:%d ====\n", __func__, ch); - print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_NONE, 32, 4, - rd_max_zero, MAX_ROUND * sizeof(u32), false); - - dev_info(combrxphy->dev, - "%s max value of channel:%d ====\n", __func__, ch); - print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_NONE, 32, 4, - rd_max_val, MAX_ROUND * sizeof(u32), false); - } - - for (i = 0; i < MAX_ROUND; i++) { - if (rd_max_zero[i] > max) { - max = rd_max_zero[i]; - max_v = rd_max_val[i]; - rd = i; - } else if (rd_max_zero[i] == max && rd_max_val[i] > max_v) { - max = rd_max_zero[i]; - max_v = rd_max_val[i]; - rd = i; - } - } - - dev_dbg(combrxphy->dev, "%s channel:%d, rd:%d\n", __func__, ch, rd); - return rd; -} - -static void rk628_combrxphy_get_data_of_round(struct rk628_combrxphy - *combrxphy, u32 *data) -{ - u32 i; - - for (i = 0; i < MAX_DATA_NUM; i++) - regmap_read(combrxphy->regmap, REG(0x6740 + i * 4), &data[i]); -} - -static void -rk628_combrxphy_set_dc_gain(struct rk628_combrxphy *combrxphy, - u32 x, u32 y, u32 z) -{ - u32 val; - u32 dc_gain_ch0, dc_gain_ch1, dc_gain_ch2; - - dev_dbg(combrxphy->dev, "channel dc gain ch0:%d, ch1:%d, ch2:%d\n", - x, y, z); - - dc_gain_ch0 = x & 0xf; - dc_gain_ch1 = y & 0xf; - dc_gain_ch2 = z & 0xf; - regmap_read(combrxphy->regmap, REG(0x661c), &val); - - val = (val & 0xff0f0f0f) | (dc_gain_ch0 << 20) | (dc_gain_ch1 << 12) | - (dc_gain_ch2 << 4); - regmap_write(combrxphy->regmap, REG(0x661c), val); -} - -static void rk628_combrxphy_set_sample_edge_round(struct rk628_combrxphy - *combrxphy, u32 x, u32 y, u32 z) -{ - u32 val; - u32 equ_gain_ch0, equ_gain_ch1, equ_gain_ch2; - - dev_dbg(combrxphy->dev, "channel equ gain ch0:%d, ch1:%d, ch2:%d\n", - x, y, z); - - equ_gain_ch0 = (x & 0xf); - equ_gain_ch1 = (y & 0xf); - equ_gain_ch2 = (z & 0xf); - regmap_read(combrxphy->regmap, REG(0x6618), &val); - val = (val & 0xff00f0ff) | (equ_gain_ch1 << 20) | - (equ_gain_ch0 << 16) | (equ_gain_ch2 << 8); - regmap_write(combrxphy->regmap, REG(0x6618), val); -} - -static void rk628_combrxphy_start_sample_edge(struct rk628_combrxphy *combrxphy) -{ - u32 val; - - regmap_read(combrxphy->regmap, REG(0x66f0), &val); - val &= 0xfffff1ff; - regmap_write(combrxphy->regmap, REG(0x66f0), val); - regmap_read(combrxphy->regmap, REG(0x66f0), &val); - val = (val & 0xfffff1ff) | (0x7 << 9); - regmap_write(combrxphy->regmap, REG(0x66f0), val); -} - -static void -rk628_combrxphy_set_sample_edge_mode(struct rk628_combrxphy *combrxphy, - int ch) -{ - u32 val; - - regmap_read(combrxphy->regmap, REG(0x6634), &val); - val = val & (~(0xf << ((ch + 1) * 4))); - regmap_write(combrxphy->regmap, REG(0x6634), val); -} - -static void rk628_combrxphy_select_channel(struct rk628_combrxphy *combrxphy, - int ch) -{ - u32 val; - - regmap_read(combrxphy->regmap, REG(0x6700), &val); - val = (val & 0xfffffffc) | (ch & 0x3); - regmap_write(combrxphy->regmap, REG(0x6700), val); -} - -static void rk628_combrxphy_cfg_6730(struct rk628_combrxphy *combrxphy) -{ - u32 val; - - regmap_read(combrxphy->regmap, REG(0x6730), &val); - val = (val & 0xffff0000) | 0x1; - regmap_write(combrxphy->regmap, REG(0x6730), val); -} - -static void rk628_combrxphy_sample_edge_procedure_for_cable( - struct rk628_combrxphy *combrxphy, u32 cdr_mode) -{ - u32 n, ch; - u32 data[MAX_DATA_NUM]; - u32 data_in[MAX_DATA_NUM]; - u32 round_max_zero[MAX_CHANNEL][MAX_ROUND]; - u32 round_max_value[MAX_CHANNEL][MAX_ROUND]; - u32 ch_round[MAX_CHANNEL]; - u32 edge, dc_gain; - u32 rd_offset; - - /* Step1: set sample edge mode for channel 0~2 */ - for (ch = 0; ch < MAX_CHANNEL; ch++) - rk628_combrxphy_set_sample_edge_mode(combrxphy, ch); - - /* step2: once per round */ - for (ch = 0; ch < MAX_CHANNEL; ch++) { - rk628_combrxphy_select_channel(combrxphy, ch); - rk628_combrxphy_cfg_6730(combrxphy); - } - - /* step3: config sample edge until the end of one frame - * (for example 1080p:2200*1125=32’h25c3f8) - */ - if (cdr_mode < 16) { - dc_gain = 0; - rd_offset = 0; - } else if (cdr_mode < 18) { - dc_gain = 1; - rd_offset = 0; - } else { - dc_gain = 3; - rd_offset = 2; - } - - /* When the pix clk is the same, the low frame rate resolution is used - * to calculate the sampling window (the frame rate is not less than - * 30). The sampling delay time is configured as 40ms. - */ - if (cdr_mode <= 1) { /* 27M vic17 720x576P50 */ - edge = 864 * 625; - } else if (cdr_mode <= 4) { /* 59.4M vic81 1680x720P30 */ - edge = 2640 * 750; - } else if (cdr_mode <= 7) { /* 74.25M vic34 1920x1080P30 */ - edge = 2200 * 1125; - } else if (cdr_mode <= 14) { /* 119M vic88 2560x1180P30 */ - edge = 3520 * 1125; - } else if (cdr_mode <= 16) { /* 148.5M vic31 1920x1080P50 */ - edge = 2640 * 1125; - } else if (cdr_mode <= 17) { /* 162M vic89 2560x1080P50 */ - edge = 3300 * 1125; - } else if (cdr_mode <= 18) { /* 297M vic95 3840x2160P30 */ - edge = 4400 * 2250; - } else { /* unkonw vic16 1920x1080P60 */ - edge = 2200 * 1125; - } - - dev_info(combrxphy->dev, - "cdr_mode:%d, dc_gain:%d, rd_offset:%d, edge:%#x\n", - cdr_mode, dc_gain, rd_offset, edge); - for (ch = 0; ch < MAX_CHANNEL; ch++) { - rk628_combrxphy_select_channel(combrxphy, ch); - regmap_write(combrxphy->regmap, REG(0x6708), edge); - } - - rk628_combrxphy_set_dc_gain(combrxphy, dc_gain, dc_gain, dc_gain); - for (n = rd_offset; n < (rd_offset + MAX_ROUND); n++) { - /* step4:set sample edge round value n,n=0(n=0~31) */ - rk628_combrxphy_set_sample_edge_round(combrxphy, n, n, n); - /* step5:start sample edge */ - rk628_combrxphy_start_sample_edge(combrxphy); - /* step6:waiting more than one frame time */ - usleep_range(40*1000, 41*1000); - for (ch = 0; ch < MAX_CHANNEL; ch++) { - /* step7: get data of round n */ - rk628_combrxphy_select_channel(combrxphy, ch); - rk628_combrxphy_get_data_of_round(combrxphy, data); - rk628_combrxphy_set_data_of_round(data, data_in); - /* step8: get the max constant value of round n */ - rk628_combrxphy_max_zero_of_round(combrxphy, data_in, - round_max_zero[ch], round_max_value[ch], - n - rd_offset, ch); - } - } - - /* step9: after finish round, get the max constant value and - * corresponding value n. - */ - for (ch = 0; ch < MAX_CHANNEL; ch++) { - ch_round[ch] = rk628_combrxphy_chose_round_for_ch(combrxphy, - round_max_zero[ch], round_max_value[ch], ch) - + rd_offset; - } - dev_info(combrxphy->dev, "last equ gain ch0:%d, ch1:%d, ch2:%d\n", - ch_round[0], ch_round[1], ch_round[2]); - - /* step10: write result to sample edge round value */ - rk628_combrxphy_set_sample_edge_round(combrxphy, ch_round[0], - ch_round[1], ch_round[2]); - - /* do step5, step6 again */ - /* step5:start sample edge */ - rk628_combrxphy_start_sample_edge(combrxphy); - /* step6:waiting more than one frame time */ - usleep_range(40*1000, 41*1000); -} - -static void -rk628_combrxphy_sample_edge_procedure(struct rk628_combrxphy *combrxphy, - int f, u32 rd_offset) -{ - u32 n, ch; - u32 data[MAX_DATA_NUM]; - u32 data_in[MAX_DATA_NUM]; - u32 round_max_zero[MAX_CHANNEL][MAX_ROUND]; - u32 round_max_value[MAX_CHANNEL][MAX_ROUND]; - u32 ch_round[MAX_CHANNEL]; - u32 edge, dc_gain; - - dev_dbg(combrxphy->dev, "%s in!", __func__); - /* Step1: set sample edge mode for channel 0~2 */ - for (ch = 0; ch < MAX_CHANNEL; ch++) - rk628_combrxphy_set_sample_edge_mode(combrxphy, ch); - - dev_dbg(combrxphy->dev, "step1 set sample edge mode ok!"); - - /* step2: once per round */ - for (ch = 0; ch < MAX_CHANNEL; ch++) { - rk628_combrxphy_select_channel(combrxphy, ch); - rk628_combrxphy_cfg_6730(combrxphy); - } - dev_dbg(combrxphy->dev, "step2 once per round ok!"); - - /* - * step3:config sample edge until the end of one frame - * (for example 1080p:2200*1125=32’h25c3f8) - */ - switch (f) { - case 27000: - edge = 858 * 525; - dc_gain = 0; - break; - case 64000: - edge = 1317 * 810; - dc_gain = 0; - break; - case 74250: - edge = 1650 * 750; - dc_gain = 0; - break; - case 148500: - edge = 2200 * 1125; - dc_gain = 1; - break; - case 297000: - dc_gain = 3; - edge = 4400 * 2250; - break; - case 594000: - dc_gain = 0xf; - edge = 4400 * 2250; - break; - default: - edge = 2200 * 1125; - dc_gain = 1; - break; - } - dev_dbg(combrxphy->dev, "===>>> f:%d, edge:%#x", f, edge); - for (ch = 0; ch < MAX_CHANNEL; ch++) { - rk628_combrxphy_select_channel(combrxphy, ch); - regmap_write(combrxphy->regmap, REG(0x6708), edge); - } - dev_dbg(combrxphy->dev, "step3 cfg sample edge ok!"); - - rk628_combrxphy_set_dc_gain(combrxphy, dc_gain, dc_gain, dc_gain); - - for (n = rd_offset; n < (rd_offset + MAX_ROUND); n++) { - /* step4:set sample edge round value n,n=0(n=0~31) */ - rk628_combrxphy_set_sample_edge_round(combrxphy, n, n, n); - dev_dbg(combrxphy->dev, "step4 ok!"); - /* step5:start sample edge */ - rk628_combrxphy_start_sample_edge(combrxphy); - dev_dbg(combrxphy->dev, "step5 ok!"); - /* step6:waiting more than one frame time */ - usleep_range(40*1000, 41*1000); - for (ch = 0; ch < MAX_CHANNEL; ch++) { - /* step7:get data of round n */ - rk628_combrxphy_select_channel(combrxphy, ch); - dev_dbg(combrxphy->dev, "step7 set ch ok!"); - rk628_combrxphy_get_data_of_round(combrxphy, data); - dev_dbg(combrxphy->dev, "step7 get data ok!"); - rk628_combrxphy_set_data_of_round(data, data_in); - dev_dbg(combrxphy->dev, "step7 set data ok!"); - rk628_combrxphy_max_zero_of_round(combrxphy, data_in, - round_max_zero[ch], - round_max_value[ch], - n - rd_offset, ch); - } - } - for (ch = 0; ch < MAX_CHANNEL; ch++) - ch_round[ch] = - rk628_combrxphy_chose_round_for_ch(combrxphy, - round_max_zero[ch], - round_max_value[ch], - ch) + rd_offset; - - /* - * step8:after finish round 31, get the max constant value and - * corresponding value n. - * write result to sample edge round value. - */ - rk628_combrxphy_set_sample_edge_round(combrxphy, ch_round[0], - ch_round[1], ch_round[2]); - - /* do step5, step6 again */ - dev_dbg(combrxphy->dev, "do step5 step6 again!"); - rk628_combrxphy_start_sample_edge(combrxphy); - usleep_range(40*1000, 41*1000); -} - -static int rk628_combrxphy_try_clk_detect(struct rk628_combrxphy *combrxphy) -{ - u32 val, i; - int ret; - - ret = -1; - reset_control_assert(combrxphy->rstc); - usleep_range(10, 20); - reset_control_deassert(combrxphy->rstc); - usleep_range(10, 20); - - /* step1: set pin_rst_n to 1’b0.wait 1 period(1us).release reset */ - /* step2: select pll clock src and enable auto check */ - regmap_read(combrxphy->regmap, REG(0x6630), &val); - /* clear bit0 and bit3 */ - val = val & 0xfffffff6; - regmap_write(combrxphy->regmap, REG(0x6630), val); - /* step3: select hdmi mode and enable chip, read reg6654, - * make sure auto setup done. - */ - /* auto fsm reset related */ - regmap_read(combrxphy->regmap, REG(0x6630), &val); - val = val | BIT(24); - regmap_write(combrxphy->regmap, REG(0x6630), val); - /* pull down ana rstn */ - regmap_read(combrxphy->regmap, REG(0x66f0), &val); - val = val & 0xfffffeff; - regmap_write(combrxphy->regmap, REG(0x66f0), val); - /* pull down dig rstn */ - regmap_read(combrxphy->regmap, REG(0x66f4), &val); - val = val & 0xfffffffe; - regmap_write(combrxphy->regmap, REG(0x66f4), val); - /* pull up ana rstn */ - regmap_read(combrxphy->regmap, REG(0x66f0), &val); - val = val | 0x100; - regmap_write(combrxphy->regmap, REG(0x66f0), val); - /* pull up dig rstn */ - regmap_read(combrxphy->regmap, REG(0x66f4), &val); - val = val | 0x1; - regmap_write(combrxphy->regmap, REG(0x66f4), val); - - regmap_read(combrxphy->regmap, REG(0x66f0), &val); - /* set bit0 and bit2 to 1*/ - val = (val & 0xfffffff8) | 0x5; - regmap_write(combrxphy->regmap, REG(0x66f0), val); - - /* auto fsm en = 0 */ - regmap_read(combrxphy->regmap, REG(0x66f0), &val); - /* set bit0 and bit2 to 1*/ - val = (val & 0xfffffff8) | 0x4; - regmap_write(combrxphy->regmap, REG(0x66f0), val); - - for (i = 0; i < 10; i++) { - usleep_range(500, 510); - regmap_read(combrxphy->regmap, REG(0x6654), &val); - if ((val & 0xf0000000) == 0x80000000) { - ret = 0; - dev_info(combrxphy->dev, "clock detected!"); - break; - } - } - - return ret; -} - -static int -rk628_combrxphy_set_hdmi_mode_for_cable(struct rk628_combrxphy *combrxphy, - int f) -{ - u32 val, val_a, val_b, data_a, data_b; - u32 i, j, count, ret; - u32 cdr_mode, cdr_data, pll_man; - u32 tmds_bitrate_per_lane; - u32 cdr_data_min, cdr_data_max; - - /* - * use the mode of automatic clock detection, only supports fixed TMDS - * frequency.Refer to register 0x6654[21:16]: - * 5'd31:Error mode - * 5'd30:manual mode detected - * 5'd18:rx3p clock = 297MHz - * 5'd17:rx3p clock = 162MHz - * 5'd16:rx3p clock = 148.5MHz - * 5'd15:rx3p clock = 135MHz - * 5'd14:rx3p clock = 119MHz - * 5'd13:rx3p clock = 108MHz - * 5'd12:rx3p clock = 101MHz - * 5'd11:rx3p clock = 92.8125MHz - * 5'd10:rx3p clock = 88.75MHz - * 5'd9:rx3p clock = 85.5MHz - * 5'd8:rx3p clock = 83.5MHz - * 5'd7:rx3p clock = 74.25MHz - * 5'd6:rx3p clock = 68.25MHz - * 5'd5:rx3p clock = 65MHz - * 5'd4:rx3p clock = 59.4MHz - * 5'd3:rx3p clock = 40MHz - * 5'd2:rx3p clock = 33.75MHz - * 5'd1:rx3p clock = 27MHz - * 5'd0:rx3p clock = 25.17MHz - */ - - const u32 cdr_mode_to_khz[] = { - 25170, 27000, 33750, 40000, 59400, 65000, 68250, - 74250, 83500, 85500, 88750, 92812, 101000, 108000, - 119000, 135000, 148500, 162000, 297000, - }; - - for (i = 0; i < CLK_DET_TRY_TIMES; i++) { - if (rk628_combrxphy_try_clk_detect(combrxphy) >= 0) - break; - usleep_range(100*1000, 100*1000); - } - regmap_read(combrxphy->regmap, REG(0x6654), &val); - dev_info(combrxphy->dev, "clk det over cnt:%d, reg_0x6654:%#x", i, val); - - regmap_read(combrxphy->regmap, REG(0x6620), &val); - if ((i == CLK_DET_TRY_TIMES) || - ((val & 0x7f000000) == 0) || - ((val & 0x007f0000) == 0) || - ((val & 0x00007f00) == 0) || - ((val & 0x0000007f) == 0)) { - dev_info(combrxphy->dev, - "clock detected failed, cfg resistance manual!"); - regmap_write(combrxphy->regmap, REG(0x6620), 0x66666666); - regmap_update_bits(combrxphy->regmap, REG(0x6604), BIT(31), - BIT(31)); - usleep_range(1000, 1100); - } - - /* step4: get cdr_mode and cdr_data */ - for (j = 0; j < CLK_STABLE_LOOP_CNT ; j++) { - cdr_data_min = 0xffffffff; - cdr_data_max = 0; - - for (i = 0; i < CLK_DET_TRY_TIMES; i++) { - regmap_read(combrxphy->regmap, REG(0x6654), &val); - cdr_data = val & 0xffff; - if (cdr_data <= cdr_data_min) - cdr_data_min = cdr_data; - if (cdr_data >= cdr_data_max) - cdr_data_max = cdr_data; - udelay(50); - } - - if (((cdr_data_max - cdr_data_min) <= CLK_STABLE_THRESHOLD) && - (cdr_data_min >= 60)) { - dev_info(combrxphy->dev, "clock stable!"); - break; - } - } - - if (j == CLK_STABLE_LOOP_CNT) { - regmap_read(combrxphy->regmap, REG(0x6630), &val_a); - regmap_read(combrxphy->regmap, REG(0x6608), &val_b); - dev_err(combrxphy->dev, - "err, clk not stable, reg_0x6630:%#x, reg_0x6608:%#x", - val_a, val_b); - - return -EINVAL; - } - - regmap_read(combrxphy->regmap, REG(0x6654), &val); - if ((val & 0x1f0000) == 0x1f0000) { - regmap_read(combrxphy->regmap, REG(0x6630), &val_a); - regmap_read(combrxphy->regmap, REG(0x6608), &val_b); - dev_err(combrxphy->dev, - "clock error: 0x1f, reg_0x6630:%#x, reg_0x6608:%#x", - val_a, val_b); - - return -EINVAL; - } - - cdr_mode = (val >> 16) & 0x1f; - cdr_data = val & 0xffff; - dev_info(combrxphy->dev, "cdr_mode:%d, cdr_data:%d\n", cdr_mode, - cdr_data); - - /* step5: manually configure PLL - * cfg reg 66a8 tmds clock div2 for rgb/yuv444 as default - * reg 662c[16:8] pll_pre_div - */ - if (f <= 340000) { - regmap_write(combrxphy->regmap, REG(0x662c), 0x01000500); - regmap_write(combrxphy->regmap, REG(0x66a8), 0x0000c600); - } else { - regmap_write(combrxphy->regmap, REG(0x662c), 0x01001400); - regmap_write(combrxphy->regmap, REG(0x66a8), 0x0000c600); - } - - /* when tmds bitrate/lane <= 340M, bitrate/lane = pix_clk * 10 */ - tmds_bitrate_per_lane = cdr_mode_to_khz[cdr_mode] * 10; - if (tmds_bitrate_per_lane < 400000) - pll_man = 0x7960c; - else if (tmds_bitrate_per_lane < 600000) - pll_man = 0x7750c; - else if (tmds_bitrate_per_lane < 800000) - pll_man = 0x7964c; - else if (tmds_bitrate_per_lane < 1000000) - pll_man = 0x7754c; - else if (tmds_bitrate_per_lane < 1600000) - pll_man = 0x7a108; - else if (tmds_bitrate_per_lane < 2400000) - pll_man = 0x73588; - else if (tmds_bitrate_per_lane < 3400000) - pll_man = 0x7a108; - else - pll_man = 0x7f0c8; - - dev_info(combrxphy->dev, "cdr_mode:%d, pll_man:%#x\n", cdr_mode, - pll_man); - regmap_write(combrxphy->regmap, REG(0x6630), pll_man); - - /* step6: EQ and SAMPLE cfg */ - rk628_combrxphy_sample_edge_procedure_for_cable(combrxphy, cdr_mode); - - /* step7: Deassert fifo reset,enable fifo write and read */ - /* reset rx_infifo */ - regmap_write(combrxphy->regmap, REG(0x66a0), 0x00000003); - /* rx_infofo wr/rd disable */ - regmap_write(combrxphy->regmap, REG(0x66b0), 0x00080060); - /* deassert rx_infifo reset */ - regmap_write(combrxphy->regmap, REG(0x66a0), 0x00000083); - /* enable rx_infofo wr/rd en */ - regmap_write(combrxphy->regmap, REG(0x66b0), 0x00380060); - /* cfg 0x2260 high_8b to 0x66ac high_8b, low_8b to 0x66b0 low_8b */ - regmap_update_bits(combrxphy->regmap, REG(0x66ac), GENMASK(31, 24), - UPDATE(0x22, 31, 24)); - usleep_range(5*1000, 6*1000); - - /* step8: check all 3 data channels alignment */ - count = 0; - for (i = 0; i < 100; i++) { - usleep_range(100, 110); - regmap_read(combrxphy->regmap, REG(0x66b4), &data_a); - regmap_read(combrxphy->regmap, REG(0x66b8), &data_b); - /* ch0 ch1 ch2 lock */ - if (((data_a & 0x00ff00ff) == 0x00ff00ff) && - ((data_b & 0xff) == 0xff)) { - count++; - } - } - - if (count >= 100) { - dev_info(combrxphy->dev, "channel alignment done"); - dev_info(combrxphy->dev, "rx initial done"); - ret = 0; - } else if (count > 0) { - dev_err(combrxphy->dev, "link not stable, count:%d of 100", - count); - ret = 0; - } else { - dev_err(combrxphy->dev, "channel alignment failed!"); - ret = -EINVAL; - } - - return ret; -} - -static int rk628_combrxphy_set_hdmi_mode(struct rk628_combrxphy *combrxphy, - int bus_width) -{ - u32 val, data_a, data_b, f, val2 = 0; - int i, ret, count; - u32 pll_man, rd_offset; - bool is_yuv420; - - is_yuv420 = bus_width & BIT(30); - - if (is_yuv420) - f = (bus_width & 0xffffff) / 2; - else - f = bus_width & 0xffffff; - - dev_dbg(combrxphy->dev, "f:%d\n", f); - - regmap_read(combrxphy->regmap, REG(0x6630), &val); - val &= ~BIT(23); - val |= 0x18; - regmap_write(combrxphy->regmap, REG(0x6630), val); - - /* enable cal */ - regmap_read(combrxphy->regmap, REG(0x6610), &val); - val |= 0x18000000; - regmap_write(combrxphy->regmap, REG(0x6610), val); - - usleep_range(10*1000, 11*1000); - /* disable cal */ - val &= ~BIT(28); - val |= BIT(27); - regmap_write(combrxphy->regmap, REG(0x6610), val); - - /* save cal val */ - regmap_read(combrxphy->regmap, REG(0x6614), &val); - if (!(val & 0x3f00)) { - dev_err(combrxphy->dev, "resistor error\n"); - return -EINVAL; - } - - val &= 0x3f00; - val = val >> 8; - val2 |= 0x40404040; - val2 |= val << 24 | val << 16 | val << 8 | val; - - /* rtm inc */ - regmap_read(combrxphy->regmap, REG(0x6604), &val); - val |= BIT(31); - regmap_write(combrxphy->regmap, REG(0x6604), val); - - regmap_write(combrxphy->regmap, REG(0x6620), val2); - - /* rtm en bypass */ - regmap_read(combrxphy->regmap, REG(0x6600), &val); - val |= BIT(7); - regmap_write(combrxphy->regmap, REG(0x6600), val); - - /* rtm prot en bypass */ - regmap_read(combrxphy->regmap, REG(0x6610), &val); - val |= 0x80f000; - regmap_write(combrxphy->regmap, REG(0x6610), val); - - regmap_read(combrxphy->regmap, REG(0x661c), &val); - val |= 0x81000000; - regmap_write(combrxphy->regmap, REG(0x661c), val); - - /* enable pll */ - regmap_read(combrxphy->regmap, REG(0x6630), &val); - val &= ~BIT(4); - val |= BIT(3); - regmap_write(combrxphy->regmap, REG(0x6630), val); - - /* equ en */ - regmap_read(combrxphy->regmap, REG(0x6618), &val); - val |= BIT(4); - regmap_write(combrxphy->regmap, REG(0x6618), val); - - regmap_read(combrxphy->regmap, REG(0x6614), &val); - val |= 0x10900000; - regmap_write(combrxphy->regmap, REG(0x6614), val); - - regmap_read(combrxphy->regmap, REG(0x6610), &val); - val |= 0xf00; - regmap_write(combrxphy->regmap, REG(0x6610), val); - - regmap_read(combrxphy->regmap, REG(0x6630), &val); - val |= 0x870000; - regmap_write(combrxphy->regmap, REG(0x6630), val); - - udelay(10); - - /* get cdr_mode,make sure cdr_mode != 5’h1f */ - regmap_read(combrxphy->regmap, REG(0x6654), &val); - if ((val & 0x1f0000) == 0x1f0000) - dev_err(combrxphy->dev, "error,clock error!"); - - /* manually configure PLL */ - if (f <= 340000) { - regmap_write(combrxphy->regmap, REG(0x662c), 0x01000500); - if (is_yuv420) - regmap_write(combrxphy->regmap, REG(0x66a8), - 0x0000c000); - else - regmap_write(combrxphy->regmap, REG(0x66a8), - 0x0000c600); - } else { - regmap_write(combrxphy->regmap, REG(0x662c), 0x01001400); - regmap_write(combrxphy->regmap, REG(0x66a8), 0x0000c600); - } - - switch (f) { - case 27000: - case 64000: - case 74250: - rd_offset = 0; - pll_man = 0x7964c; - break; - case 148500: - pll_man = 0x7a1c8; - rd_offset = 0; - break; - case 297000: - pll_man = 0x7a108; - rd_offset = 2; - break; - case 594000: - pll_man = 0x7f0c8; - rd_offset = 4; - break; - default: - pll_man = 0x7964c; - rd_offset = 1; - break; - } - - pll_man |= BIT(23); - regmap_write(combrxphy->regmap, REG(0x6630), pll_man); - - /* EQ and SAMPLE cfg */ - rk628_combrxphy_sample_edge_procedure(combrxphy, f, rd_offset); - - /* Deassert fifo reset,enable fifo write and read */ - regmap_write(combrxphy->regmap, REG(0x66a0), 0x00000003); - regmap_write(combrxphy->regmap, REG(0x66b0), 0x00080060); - regmap_write(combrxphy->regmap, REG(0x66a0), 0x00000083); - regmap_write(combrxphy->regmap, REG(0x66b0), 0x00380060); - regmap_update_bits(combrxphy->regmap, REG(0x66ac), GENMASK(31, 24), - UPDATE(0x22, 31, 24)); - usleep_range(10*1000, 11*1000); - - /* check all 3 data channels alignment */ - count = 0; - for (i = 0; i < 100; i++) { - udelay(100); - regmap_read(combrxphy->regmap, REG(0x66b4), &data_a); - regmap_read(combrxphy->regmap, REG(0x66b8), &data_b); - /* ch0 ch1 ch2 lock */ - if (((data_a & 0x00ff00ff) == 0x00ff00ff) && - ((data_b & 0xff) == 0xff)) - count++; - } - - if (count >= 100) { - dev_info(combrxphy->dev, "channel alignment done"); - ret = 0; - } else if (count > 0) { - dev_err(combrxphy->dev, "not stable, count:%d of 100", count); - ret = -EINVAL; - } else { - dev_err(combrxphy->dev, "channel alignment failed!"); - ret = -EINVAL; - } - - return ret; -} - -static int rk628_combrxphy_power_on(struct phy *phy) -{ - struct rk628_combrxphy *combrxphy = phy_get_drvdata(phy); - int f = phy_get_bus_width(phy); - int ret; - - /* Bit31 is used to distinguish HDMI cable mode and direct - * connection mode. - * Bit31: 0 -direct connection mode; - * 1 -cable mode; - */ - combrxphy->is_cable_mode = (f & BIT(31)) ? true : false; - dev_dbg(combrxphy->dev, "%s\n", __func__); - clk_prepare_enable(combrxphy->pclk); - reset_control_assert(combrxphy->rstc); - udelay(10); - reset_control_deassert(combrxphy->rstc); - udelay(10); - - if (combrxphy->is_cable_mode) { - f = f & 0x7fffffff; - ret = rk628_combrxphy_set_hdmi_mode_for_cable(combrxphy, f); - } else { - ret = rk628_combrxphy_set_hdmi_mode(combrxphy, f); - } - - return ret; -} - -static int rk628_combrxphy_power_off(struct phy *phy) -{ - struct rk628_combrxphy *combrxphy = phy_get_drvdata(phy); - - dev_dbg(combrxphy->dev, "%s\n", __func__); - reset_control_assert(combrxphy->rstc); - udelay(10); - clk_disable_unprepare(combrxphy->pclk); - - return 0; -} - -static const struct phy_ops rk628_combrxphy_ops = { - .power_on = rk628_combrxphy_power_on, - .power_off = rk628_combrxphy_power_off, - .owner = THIS_MODULE, -}; - -static const struct regmap_range rk628_combrxphy_readable_ranges[] = { - regmap_reg_range(REG(0x6600), REG(0x665b)), - regmap_reg_range(REG(0x66a0), REG(0x66db)), - regmap_reg_range(REG(0x66f0), REG(0x66ff)), - regmap_reg_range(REG(0x6700), REG(0x6790)), -}; - -static const struct regmap_access_table rk628_combrxphy_readable_table = { - .yes_ranges = rk628_combrxphy_readable_ranges, - .n_yes_ranges = ARRAY_SIZE(rk628_combrxphy_readable_ranges), -}; - -static const struct regmap_config rk628_combrxphy_regmap_cfg = { - .name = "combrxphy", - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .max_register = COMBRXPHY_MAX_REGISTER, - .reg_format_endian = REGMAP_ENDIAN_LITTLE, - .val_format_endian = REGMAP_ENDIAN_LITTLE, - .rd_table = &rk628_combrxphy_readable_table, -}; - -static int rk628_combrxphy_probe(struct platform_device *pdev) -{ - struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent); - struct device *dev = &pdev->dev; - struct rk628_combrxphy *combrxphy; - struct phy_provider *phy_provider; - struct phy *phy; - int ret; - - if (!of_device_is_available(dev->of_node)) - return -ENODEV; - - combrxphy = devm_kzalloc(dev, sizeof(*combrxphy), GFP_KERNEL); - if (!combrxphy) - return -ENOMEM; - - combrxphy->dev = dev; - combrxphy->parent = rk628; - platform_set_drvdata(pdev, combrxphy); - - combrxphy->pclk = devm_clk_get(dev, "pclk"); - if (IS_ERR(combrxphy->pclk)) { - ret = PTR_ERR(combrxphy->pclk); - dev_err(dev, "failed to get pclk: %d\n", ret); - return ret; - } - - combrxphy->rstc = of_reset_control_get(dev->of_node, NULL); - if (IS_ERR(combrxphy->rstc)) { - ret = PTR_ERR(combrxphy->rstc); - dev_err(dev, "failed to get reset control: %d\n", ret); - return ret; - } - - combrxphy->regmap = devm_regmap_init_i2c(rk628->client, - &rk628_combrxphy_regmap_cfg); - if (IS_ERR(combrxphy->regmap)) { - ret = PTR_ERR(combrxphy->regmap); - dev_err(dev, "failed to allocate host register map: %d\n", ret); - return ret; - } - - phy = devm_phy_create(dev, NULL, &rk628_combrxphy_ops); - if (IS_ERR(phy)) { - ret = PTR_ERR(phy); - dev_err(dev, "failed to create phy: %d\n", ret); - return ret; - } - - phy_set_drvdata(phy, combrxphy); - - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) { - ret = PTR_ERR(phy_provider); - dev_err(dev, "failed to register phy provider: %d\n", ret); - return ret; - } - - return 0; -} - -static const struct of_device_id rk628_combrxphy_of_match[] = { - { .compatible = "rockchip,rk628-combrxphy", }, - {} -}; -MODULE_DEVICE_TABLE(of, rk628_combrxphy_of_match); - -static struct platform_driver rk628_combrxphy_driver = { - .driver = { - .name = "rk628-combrxphy", - .of_match_table = of_match_ptr(rk628_combrxphy_of_match), - }, - .probe = rk628_combrxphy_probe, -}; -module_platform_driver(rk628_combrxphy_driver); - -MODULE_AUTHOR("Algea Cao "); -MODULE_DESCRIPTION("Rockchip RK628 HDMI Combo RX PHY driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/rockchip/rk628/rk628_combtxphy.c b/drivers/gpu/drm/rockchip/rk628/rk628_combtxphy.c deleted file mode 100644 index cbe7923139b7..000000000000 --- a/drivers/gpu/drm/rockchip/rk628/rk628_combtxphy.c +++ /dev/null @@ -1,520 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2020 Rockchip Electronics Co. Ltd. - * - * Author: Wyon Bi - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rk628_combtxphy.h" - -#define REG(x) ((x) + 0x90000) - -#define COMBTXPHY_CON0 REG(0x0000) -#define SW_TX_IDLE_MASK GENMASK(29, 20) -#define SW_TX_IDLE(x) UPDATE(x, 29, 20) -#define SW_TX_PD_MASK GENMASK(17, 8) -#define SW_TX_PD(x) UPDATE(x, 17, 8) -#define SW_BUS_WIDTH_MASK GENMASK(6, 5) -#define SW_BUS_WIDTH_7BIT UPDATE(0x3, 6, 5) -#define SW_BUS_WIDTH_8BIT UPDATE(0x2, 6, 5) -#define SW_BUS_WIDTH_9BIT UPDATE(0x1, 6, 5) -#define SW_BUS_WIDTH_10BIT UPDATE(0x0, 6, 5) -#define SW_PD_PLL_MASK BIT(4) -#define SW_PD_PLL BIT(4) -#define SW_GVI_LVDS_EN_MASK BIT(3) -#define SW_GVI_LVDS_EN BIT(3) -#define SW_MIPI_DSI_EN_MASK BIT(2) -#define SW_MIPI_DSI_EN BIT(2) -#define SW_MODULEB_EN_MASK BIT(1) -#define SW_MODULEB_EN BIT(1) -#define SW_MODULEA_EN_MASK BIT(0) -#define SW_MODULEA_EN BIT(0) -#define COMBTXPHY_CON1 REG(0x0004) -#define COMBTXPHY_CON2 REG(0x0008) -#define COMBTXPHY_CON3 REG(0x000c) -#define COMBTXPHY_CON4 REG(0x0010) -#define COMBTXPHY_CON5 REG(0x0014) -#define SW_RATE(x) UPDATE(x, 26, 24) -#define SW_REF_DIV(x) UPDATE(x, 20, 16) -#define SW_PLL_FB_DIV(x) UPDATE(x, 14, 10) -#define SW_PLL_FRAC_DIV(x) UPDATE(x, 9, 0) -#define COMBTXPHY_CON6 REG(0x0018) -#define COMBTXPHY_CON7 REG(0x001c) -#define SW_TX_RTERM_MASK GENMASK(22, 20) -#define SW_TX_RTERM(x) UPDATE(x, 22, 20) -#define SW_TX_MODE_MASK GENMASK(17, 16) -#define SW_TX_MODE(x) UPDATE(x, 17, 16) -#define SW_TX_CTL_CON5_MASK BIT(10) -#define SW_TX_CTL_CON5(x) UPDATE(x, 10, 10) -#define SW_TX_CTL_CON4_MASK GENMASK(9, 8) -#define SW_TX_CTL_CON4(x) UPDATE(x, 9, 8) -#define BYPASS_095V_LDO_MASK BIT(3) -#define BYPASS_095V_LDO(x) UPDATE(x, 3, 3) -#define TX_COM_VOLT_ADJ_MASK GENMASK(2, 0) -#define TX_COM_VOLT_ADJ(x) UPDATE(x, 2, 0) -#define COMBTXPHY_CON8 REG(0x0020) -#define COMBTXPHY_CON9 REG(0x0024) -#define SW_DSI_FSET_EN_MASK BIT(29) -#define SW_DSI_FSET_EN BIT(29) -#define SW_DSI_RCAL_EN_MASK BIT(28) -#define SW_DSI_RCAL_EN BIT(28) -#define COMBTXPHY_CON10 REG(0x0028) -#define TX9_CKDRV_EN BIT(9) -#define TX8_CKDRV_EN BIT(8) -#define TX7_CKDRV_EN BIT(7) -#define TX6_CKDRV_EN BIT(6) -#define TX5_CKDRV_EN BIT(5) -#define TX4_CKDRV_EN BIT(4) -#define TX3_CKDRV_EN BIT(3) -#define TX2_CKDRV_EN BIT(2) -#define TX1_CKDRV_EN BIT(1) -#define TX0_CKDRV_EN BIT(0) -#define COMBTXPHY_MAX_REGISTER COMBTXPHY_CON10 - -struct rk628_combtxphy { - struct device *dev; - struct rk628 *parent; - struct regmap *grf; - struct regmap *regmap; - struct clk *pclk; - struct clk *ref_clk; - struct reset_control *rstc; - unsigned int flags; - - u16 frac_div; - u8 ref_div; - u8 fb_div; - u8 rate_div; - u8 division_mode; -}; - -static int rk628_combtxphy_dsi_power_on(struct rk628_combtxphy *combtxphy) -{ - u32 val; - int ret; - - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK | - SW_MIPI_DSI_EN_MASK, - SW_BUS_WIDTH_8BIT | SW_MIPI_DSI_EN); - - if (combtxphy->flags & COMBTXPHY_MODULEA_EN) - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_MODULEA_EN_MASK, SW_MODULEA_EN); - if (combtxphy->flags & COMBTXPHY_MODULEB_EN) - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_MODULEB_EN_MASK, SW_MODULEB_EN); - - regmap_write(combtxphy->regmap, COMBTXPHY_CON5, - SW_REF_DIV(combtxphy->ref_div - 1) | - SW_PLL_FB_DIV(combtxphy->fb_div) | - SW_PLL_FRAC_DIV(combtxphy->frac_div) | - SW_RATE(combtxphy->rate_div / 2)); - - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_PD_PLL, 0); - - ret = regmap_read_poll_timeout(combtxphy->grf, GRF_DPHY0_STATUS, - val, val & DPHY_PHYLOCK, 0, 1000); - if (ret < 0) { - dev_err(combtxphy->dev, "phy is not lock\n"); - return ret; - } - - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON9, - SW_DSI_FSET_EN_MASK | SW_DSI_RCAL_EN_MASK, - SW_DSI_FSET_EN | SW_DSI_RCAL_EN); - - usleep_range(200, 400); - - return 0; -} - -static int rk628_combtxphy_lvds_power_on(struct rk628_combtxphy *combtxphy) -{ - u32 val; - int ret; - - /* Adjust terminal resistance 133 ohm, bypass 0.95v ldo for driver. */ - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON7, - SW_TX_RTERM_MASK | SW_TX_MODE_MASK | - BYPASS_095V_LDO_MASK | TX_COM_VOLT_ADJ_MASK, - SW_TX_RTERM(6) | SW_TX_MODE(3) | - BYPASS_095V_LDO(1) | TX_COM_VOLT_ADJ(0)); - - regmap_write(combtxphy->regmap, COMBTXPHY_CON10, - TX7_CKDRV_EN | TX2_CKDRV_EN); - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK | - SW_MIPI_DSI_EN_MASK, - SW_BUS_WIDTH_7BIT | SW_GVI_LVDS_EN); - - if (combtxphy->flags & COMBTXPHY_MODULEA_EN) - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_MODULEA_EN_MASK, SW_MODULEA_EN); - if (combtxphy->flags & COMBTXPHY_MODULEB_EN) - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_MODULEB_EN_MASK, SW_MODULEB_EN); - - regmap_write(combtxphy->regmap, COMBTXPHY_CON5, - SW_REF_DIV(combtxphy->ref_div - 1) | - SW_PLL_FB_DIV(combtxphy->fb_div) | - SW_PLL_FRAC_DIV(combtxphy->frac_div) | - SW_RATE(combtxphy->rate_div / 2)); - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_PD_PLL, 0); - - ret = regmap_read_poll_timeout(combtxphy->grf, GRF_DPHY0_STATUS, - val, val & DPHY_PHYLOCK, 0, 1000); - if (ret < 0) { - dev_info(combtxphy->dev, "phy is not lock\n"); - return ret; - } - - usleep_range(100, 200); - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_TX_IDLE_MASK | SW_TX_PD_MASK, 0); - - return 0; -} - -static int rk628_combtxphy_gvi_power_on(struct rk628_combtxphy *combtxphy) -{ - int ref_div = 0; - - if (combtxphy->ref_div % 2) { - ref_div = combtxphy->ref_div - 1; - } else { - ref_div = BIT(4); - ref_div |= combtxphy->ref_div / 2 - 1; - } - regmap_write(combtxphy->regmap, COMBTXPHY_CON5, - SW_REF_DIV(ref_div) | - SW_PLL_FB_DIV(combtxphy->fb_div) | - SW_PLL_FRAC_DIV(combtxphy->frac_div) | - SW_RATE(combtxphy->rate_div / 2)); - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK | - SW_MIPI_DSI_EN_MASK | - SW_MODULEB_EN_MASK | SW_MODULEA_EN_MASK, - SW_BUS_WIDTH_10BIT | SW_GVI_LVDS_EN | - SW_MODULEB_EN | SW_MODULEA_EN); - - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_PD_PLL | SW_TX_PD_MASK, 0); - usleep_range(100, 200); - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_TX_IDLE_MASK, 0); - - return 0; -} - -int rk628_combtxphy_set_gvi_division_mode(struct phy *phy, u8 mode) -{ - struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy); - - combtxphy->division_mode = mode; - - return 0; -} -EXPORT_SYMBOL(rk628_combtxphy_set_gvi_division_mode); - -static int rk628_combtxphy_power_on(struct phy *phy) -{ - struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy); - enum phy_mode mode = phy_get_mode(phy); - - clk_prepare_enable(combtxphy->pclk); - reset_control_assert(combtxphy->rstc); - udelay(10); - reset_control_deassert(combtxphy->rstc); - udelay(10); - - regcache_mark_dirty(combtxphy->regmap); - regcache_sync(combtxphy->regmap); - - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_TX_IDLE_MASK | SW_TX_PD_MASK | SW_PD_PLL_MASK, - SW_TX_IDLE(0x3ff) | SW_TX_PD(0x3ff) | SW_PD_PLL); - - switch (mode) { - case PHY_MODE_MIPI_DPHY: - regmap_update_bits(combtxphy->grf, GRF_POST_PROC_CON, - SW_TXPHY_REFCLK_SEL_MASK, - SW_TXPHY_REFCLK_SEL(0)); - return rk628_combtxphy_dsi_power_on(combtxphy); - case PHY_MODE_LVDS: - regmap_update_bits(combtxphy->grf, GRF_POST_PROC_CON, - SW_TXPHY_REFCLK_SEL_MASK, - SW_TXPHY_REFCLK_SEL(1)); - return rk628_combtxphy_lvds_power_on(combtxphy); - default: - regmap_update_bits(combtxphy->grf, GRF_POST_PROC_CON, - SW_TXPHY_REFCLK_SEL_MASK, - SW_TXPHY_REFCLK_SEL(2)); - return rk628_combtxphy_gvi_power_on(combtxphy); - } - - return 0; -} - -static int rk628_combtxphy_power_off(struct phy *phy) -{ - struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy); - - regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0, - SW_TX_IDLE_MASK | SW_TX_PD_MASK | SW_PD_PLL_MASK | - SW_MODULEB_EN_MASK | SW_MODULEA_EN_MASK, - SW_TX_IDLE(0x3ff) | SW_TX_PD(0x3ff) | SW_PD_PLL); - - clk_disable_unprepare(combtxphy->pclk); - - return 0; -} - -static int rk628_combtxphy_set_mode(struct phy *phy, enum phy_mode mode, - int submode) -{ - struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy); - unsigned int bus_width = phy_get_bus_width(phy); - unsigned int frac_rate, fin = 24; - unsigned long fvco, fpfd; - - switch (mode) { - case PHY_MODE_MIPI_DPHY: - { - unsigned int fhsc = bus_width >> 8; - unsigned int flags = bus_width & 0xff; - - fhsc = fin * (fhsc / fin); - - if (fhsc < 80 || fhsc > 1500) - return -EINVAL; - else if (fhsc < 375) - combtxphy->rate_div = 4; - else if (fhsc < 750) - combtxphy->rate_div = 2; - else - combtxphy->rate_div = 1; - - combtxphy->flags = flags; - - fvco = fhsc * 2 * combtxphy->rate_div; - combtxphy->ref_div = 1; - combtxphy->fb_div = fvco / 8 / fin; - frac_rate = fvco - (fin * 8 * combtxphy->fb_div); - - if (frac_rate) { - frac_rate <<= 10; - frac_rate /= fin * 8; - combtxphy->frac_div = frac_rate; - } else { - combtxphy->frac_div = 0; - } - - fvco = fin * (1024 * combtxphy->fb_div + combtxphy->frac_div); - fvco *= 8; - fvco = DIV_ROUND_UP(fvco, 1024 * combtxphy->ref_div); - fhsc = fvco / 2 / combtxphy->rate_div; - phy_set_bus_width(phy, fhsc); - break; - } - case PHY_MODE_LVDS: - { - unsigned int flags = bus_width & 0xff; - unsigned int rate = (bus_width >> 8) * 7; - - combtxphy->flags = flags; - combtxphy->ref_div = 1; - combtxphy->fb_div = 14; - combtxphy->frac_div = 0; - - if (rate < 500) - combtxphy->rate_div = 4; - else if (rate < 1000) - combtxphy->rate_div = 2; - else - combtxphy->rate_div = 1; - break; - } - default: - { - unsigned int i, delta_freq, best_delta_freq, fb_div; - unsigned long ref_clk; - unsigned long long pre_clk; - - if (bus_width < 500000 || bus_width > 4000000) - return -EINVAL; - else if (bus_width < 1000000) - combtxphy->rate_div = 4; - else if (bus_width < 2000000) - combtxphy->rate_div = 2; - else - combtxphy->rate_div = 1; - fvco = bus_width * combtxphy->rate_div; - ref_clk = clk_get_rate(combtxphy->ref_clk) / 1000; /* khz */ - if (combtxphy->division_mode) - ref_clk /= 2; - - if (!ref_clk) - return -EINVAL; - - /* - * the reference clock at PFD(FPFD = ref_clk / ref_div) about - * 25MHz is recommende, FPFD must range from 16MHz to 35MHz, - * here to find the best rev_div. - */ - best_delta_freq = ref_clk; - for (i = 1; i <= 32; i++) { - fpfd = ref_clk / i; - delta_freq = abs(fpfd - 25000); - if (delta_freq < best_delta_freq) { - best_delta_freq = delta_freq; - combtxphy->ref_div = i; - } - } - - /* - * ref_clk / ref_div * 8 * fb_div = FVCO - */ - pre_clk = (unsigned long long)fvco / 8 * combtxphy->ref_div * 1024; - do_div(pre_clk, ref_clk); - fb_div = pre_clk / 1024; - - /* - * get the actually frequence - */ - bus_width = ref_clk / combtxphy->ref_div * 8; - bus_width *= fb_div; - bus_width /= combtxphy->rate_div; - - combtxphy->frac_div = 0; - combtxphy->fb_div = fb_div; - - phy_set_bus_width(phy, bus_width); - break; - } - } - - return 0; -} - -static const struct phy_ops rk628_combtxphy_ops = { - .set_mode = rk628_combtxphy_set_mode, - .power_on = rk628_combtxphy_power_on, - .power_off = rk628_combtxphy_power_off, - .owner = THIS_MODULE, -}; - -static const struct regmap_range rk628_combtxphy_readable_ranges[] = { - regmap_reg_range(COMBTXPHY_CON0, COMBTXPHY_CON10), -}; - -static const struct regmap_access_table rk628_combtxphy_readable_table = { - .yes_ranges = rk628_combtxphy_readable_ranges, - .n_yes_ranges = ARRAY_SIZE(rk628_combtxphy_readable_ranges), -}; - -static const struct regmap_config rk628_combtxphy_regmap_cfg = { - .name = "combtxphy", - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .cache_type = REGCACHE_RBTREE, - .max_register = COMBTXPHY_MAX_REGISTER, - .reg_format_endian = REGMAP_ENDIAN_LITTLE, - .val_format_endian = REGMAP_ENDIAN_LITTLE, - .rd_table = &rk628_combtxphy_readable_table, -}; - -static int rk628_combtxphy_probe(struct platform_device *pdev) -{ - struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent); - struct device *dev = &pdev->dev; - struct rk628_combtxphy *combtxphy; - struct phy_provider *phy_provider; - struct phy *phy; - int ret; - - combtxphy = devm_kzalloc(dev, sizeof(*combtxphy), GFP_KERNEL); - if (!combtxphy) - return -ENOMEM; - - combtxphy->dev = dev; - combtxphy->parent = rk628; - combtxphy->grf = rk628->grf; - platform_set_drvdata(pdev, combtxphy); - - combtxphy->pclk = devm_clk_get(dev, "pclk"); - if (IS_ERR(combtxphy->pclk)) - return PTR_ERR(combtxphy->pclk); - - combtxphy->ref_clk = devm_clk_get(dev, "ref_clk"); - if (IS_ERR(combtxphy->ref_clk)) { - dev_err(dev, "fail to get ref clk\n"); - return PTR_ERR(combtxphy->ref_clk); - } - - combtxphy->rstc = of_reset_control_get(dev->of_node, NULL); - if (IS_ERR(combtxphy->rstc)) { - ret = PTR_ERR(combtxphy->rstc); - dev_err(dev, "failed to get reset control: %d\n", ret); - return ret; - } - - combtxphy->regmap = devm_regmap_init_i2c(rk628->client, - &rk628_combtxphy_regmap_cfg); - if (IS_ERR(combtxphy->regmap)) { - ret = PTR_ERR(combtxphy->regmap); - dev_err(dev, "failed to allocate register map: %d\n", ret); - return ret; - } - - phy = devm_phy_create(dev, NULL, &rk628_combtxphy_ops); - if (IS_ERR(phy)) { - ret = PTR_ERR(phy); - dev_err(dev, "failed to create phy: %d\n", ret); - return ret; - } - - phy_set_drvdata(phy, combtxphy); - - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) { - ret = PTR_ERR(phy_provider); - dev_err(dev, "failed to register phy provider: %d\n", ret); - return ret; - } - - return 0; -} - -static const struct of_device_id rk628_combtxphy_of_match[] = { - { .compatible = "rockchip,rk628-combtxphy", }, - {} -}; -MODULE_DEVICE_TABLE(of, rk628_combtxphy_of_match); - -static struct platform_driver rk628_combtxphy_driver = { - .driver = { - .name = "rk628-combtxphy", - .of_match_table = of_match_ptr(rk628_combtxphy_of_match), - }, - .probe = rk628_combtxphy_probe, -}; -module_platform_driver(rk628_combtxphy_driver); - -MODULE_AUTHOR("Wyon Bi "); -MODULE_DESCRIPTION("Rockchip RK628 GVI/LVDS/MIPI Combo TX PHY driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/rockchip/rk628/rk628_combtxphy.h b/drivers/gpu/drm/rockchip/rk628/rk628_combtxphy.h deleted file mode 100644 index 40d785eecd67..000000000000 --- a/drivers/gpu/drm/rockchip/rk628/rk628_combtxphy.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2020 Rockchip Electronics Co. Ltd. - */ - -#ifndef RK628_COMBTXPHY_H_ -#define RK628_COMBTXPHY_H_ - -#include - -int rk628_combtxphy_set_gvi_division_mode(struct phy *phy, u8 mode); - -#endif diff --git a/drivers/gpu/drm/rockchip/rk628/rk628_dsi.c b/drivers/gpu/drm/rockchip/rk628/rk628_dsi.c deleted file mode 100644 index 766f156efb98..000000000000 --- a/drivers/gpu/drm/rockchip/rk628/rk628_dsi.c +++ /dev/null @@ -1,1395 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2020 Rockchip Electronics Co. Ltd. - * - * Author: Wyon Bi - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include