diff --git a/drivers/misc/rk628/rk628.c b/drivers/misc/rk628/rk628.c index 2b9d725ec028..c647a733607a 100644 --- a/drivers/misc/rk628/rk628.c +++ b/drivers/misc/rk628/rk628.c @@ -1225,6 +1225,7 @@ static void rk628_debugfs_create(struct rk628 *rk628) debugfs_create_file("summary", 0400, rk628->debug_dir, rk628, &rk628_debugfs_summary_fops); + rk628_rgb_decoder_create_debugfs_file(rk628); rk628_post_process_create_debugfs_file(rk628); rk628_mipi_dsi_create_debugfs_file(rk628); rk628_gvi_create_debugfs_file(rk628); diff --git a/drivers/misc/rk628/rk628.h b/drivers/misc/rk628/rk628.h index a9f8a3e152ca..4f2df6565c22 100644 --- a/drivers/misc/rk628/rk628.h +++ b/drivers/misc/rk628/rk628.h @@ -210,11 +210,23 @@ /* 0: i2c mode and mcu mode; 1: i2c mode only */ #define I2C_ONLY_FLAG BIT(6) #define GRF_SYSTEM_STATUS3 0x012c +#define DECODER_1120_LAST_LINE_NUM_MASK GENMASK(12, 0) #define GRF_SYSTEM_STATUS4 0x0130 +#define DECODER_1120_LAST_PIX_NUM_MASK GENMASK(12, 0) #define GRF_OS_REG0 0x0140 #define GRF_OS_REG1 0x0144 #define GRF_OS_REG2 0x0148 #define GRF_OS_REG3 0x014c +#define GRF_RGB_RX_DBG_MEAS0 0x0170 +#define RGB_RX_EVAL_TIME_MASK GENMASK(27, 16) +#define RGB_RX_MODET_EN BIT(1) +#define RGB_RX_DCLK_EN BIT(0) +#define GRF_RGB_RX_DBG_MEAS2 0x0178 +#define RGB_RX_CLKRATE_MASK GENMASK(15, 0) +#define GRF_RGB_RX_DBG_MEAS3 0x017c +#define RGB_RX_CNT_EN_MASK BIT(0) +#define RGB_RX_CNT_EN(x) UPDATE(x, 0, 0) +#define GRF_RGB_RX_DBG_MEAS4 0x0180 #define GRF_BT1120_TIMING_CTRL0 0x0190 #define BT1120_DSP_HS_END(x) UPDATE(x, 28, 16) #define BT1120_DSP_HTOTAL(x) UPDATE(x, 12, 0) diff --git a/drivers/misc/rk628/rk628_cru.c b/drivers/misc/rk628/rk628_cru.c index 31dc2d08e35a..da448508ed28 100644 --- a/drivers/misc/rk628/rk628_cru.c +++ b/drivers/misc/rk628/rk628_cru.c @@ -297,6 +297,26 @@ static unsigned long rk628_cru_clk_get_rate_sclk_vop(struct rk628 *rk628) return rate; } +static unsigned long rk628_cru_clk_get_rate_clk_imodet(struct rk628 *rk628) +{ + unsigned long rate, parent_rate, n; + u32 mux, div; + + rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &mux); + mux &= CLK_IMODET_SEL_MASK; + mux >>= CLK_IMODET_SEL_SHIFT; + if (mux == SCLK_VOP_SEL_GPLL) + parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL); + else + parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL); + + rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &div); + n = div & 0x1f; + rate = parent_rate / (n + 1); + + return rate; +} + static unsigned long rk628_cru_clk_set_rate_rx_read(struct rk628 *rk628, unsigned long rate) { @@ -435,6 +455,9 @@ unsigned long rk628_cru_clk_get_rate(struct rk628 *rk628, unsigned int id) case CGU_SCLK_VOP: rate = rk628_cru_clk_get_rate_sclk_vop(rk628); break; + case CGU_CLK_IMODET: + rate = rk628_cru_clk_get_rate_clk_imodet(rk628); + break; default: return 0; } diff --git a/drivers/misc/rk628/rk628_cru.h b/drivers/misc/rk628/rk628_cru.h index e13a559539de..0684d7c0d53c 100644 --- a/drivers/misc/rk628/rk628_cru.h +++ b/drivers/misc/rk628/rk628_cru.h @@ -74,6 +74,8 @@ #define CRU_CLKSEL_CON03 CRU_REG(0x008c) #define CRU_CLKSEL_CON04 CRU_REG(0x0090) #define CRU_CLKSEL_CON05 CRU_REG(0x0094) +#define CLK_IMODET_SEL_MASK BIT(5) +#define CLK_IMODET_SEL_SHIFT 5 #define CRU_CLKSEL_CON06 CRU_REG(0x0098) #define SCLK_UART_SEL(x) HIWORD_UPDATE(x, 15, 14) #define SCLK_UART_SEL_MASK GENMASK(15, 14) diff --git a/drivers/misc/rk628/rk628_rgb.c b/drivers/misc/rk628/rk628_rgb.c index 65135089676c..0a89302ebc9b 100644 --- a/drivers/misc/rk628/rk628_rgb.c +++ b/drivers/misc/rk628/rk628_rgb.c @@ -5,6 +5,7 @@ * Author: Guochun Huang */ +#include #include "rk628.h" #include "rk628_cru.h" #include "rk628_config.h" @@ -15,12 +16,77 @@ int rk628_rgb_parse(struct rk628 *rk628, struct device_node *rgb_np) return rk628_panel_info_get(rk628, rgb_np); } +static int rk628_rgb_resolution_show(struct seq_file *s, void *data) +{ + struct rk628 *rk628 = s->private; + u16 width = 0, height = 0; + u32 rgb_rx_eval_time, rgb_rx_clkrate; + u64 ref_clk, pixel_clk; + u32 val; + + rk628_i2c_read(rk628, GRF_RGB_RX_DBG_MEAS0, &val); + rgb_rx_eval_time = (val & RGB_RX_EVAL_TIME_MASK) >> 16; + + rk628_i2c_read(rk628, GRF_RGB_RX_DBG_MEAS2, &val); + rgb_rx_clkrate = val & RGB_RX_CLKRATE_MASK; + + ref_clk = rk628_cru_clk_get_rate(rk628, CGU_CLK_IMODET); + pixel_clk = ref_clk * rgb_rx_clkrate / (rgb_rx_eval_time + 1); + + if (rk628_input_is_rgb(rk628)) { + rk628_i2c_read(rk628, GRF_RGB_RX_DBG_MEAS4, &val); + height = (val >> 16) & 0xffff; + width = val & 0xffff; + } else if (rk628_input_is_bt1120(rk628)) { + rk628_i2c_read(rk628, GRF_SYSTEM_STATUS3, &val); + height = val & DECODER_1120_LAST_LINE_NUM_MASK; + + rk628_i2c_read(rk628, GRF_SYSTEM_STATUS4, &val); + width = val & DECODER_1120_LAST_PIX_NUM_MASK; + } + + seq_printf(s, "%dx%d pclk:%llu\n", width, height, pixel_clk); + + return 0; +} + +static int rk628_rgb_resolution_open(struct inode *inode, struct file *file) +{ + return single_open(file, rk628_rgb_resolution_show, inode->i_private); +} + +static const struct file_operations rk628_rgb_resolution_fops = { + .owner = THIS_MODULE, + .open = rk628_rgb_resolution_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void rk628_rgb_decoder_create_debugfs_file(struct rk628 *rk628) +{ + if (rk628->version == RK628D_VERSION) + return; + + if (rk628_input_is_rgb(rk628) || rk628_input_is_bt1120(rk628)) + debugfs_create_file("rgb_resolution", 0400, rk628->debug_dir, + rk628, &rk628_rgb_resolution_fops); +} + void rk628_rgb_decoder_enable(struct rk628 *rk628) { - /* config sw_input_mode RGB */ + /* config sw_input_mode RGB */ rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_INPUT_MODE_MASK, SW_INPUT_MODE(INPUT_MODE_RGB)); + if (rk628->version == RK628F_VERSION) { + rk628_i2c_update_bits(rk628, GRF_RGB_RX_DBG_MEAS0, + RGB_RX_MODET_EN | RGB_RX_DCLK_EN, + RGB_RX_MODET_EN | RGB_RX_DCLK_EN); + rk628_i2c_update_bits(rk628, GRF_RGB_RX_DBG_MEAS3, + RGB_RX_CNT_EN_MASK, RGB_RX_CNT_EN(1)); + } + /* pinctrl for vop pin */ rk628_i2c_write(rk628, GRF_GPIO2AB_SEL_CON, 0xffffffff); rk628_i2c_write(rk628, GRF_GPIO2C_SEL_CON, 0xffff5555); @@ -119,6 +185,11 @@ static void rk628_bt1120_decoder_timing_cfg(struct rk628 *rk628) dsp_hact_st = dsp_hbor_st + bor_left; dsp_vact_st = dsp_vbor_st + bor_up; + if (rk628->version == RK628F_VERSION) + rk628_i2c_update_bits(rk628, GRF_RGB_RX_DBG_MEAS0, + RGB_RX_MODET_EN | RGB_RX_DCLK_EN, + RGB_RX_MODET_EN | RGB_RX_DCLK_EN); + rk628_i2c_write(rk628, GRF_BT1120_TIMING_CTRL0, BT1120_DSP_HS_END(dsp_hs_end) | BT1120_DSP_HTOTAL(dsp_htotal)); rk628_i2c_write(rk628, GRF_BT1120_TIMING_CTRL1, BT1120_DSP_HACT_ST(dsp_hact_st)); diff --git a/drivers/misc/rk628/rk628_rgb.h b/drivers/misc/rk628/rk628_rgb.h index de0993f01e2a..fb5c326b3310 100644 --- a/drivers/misc/rk628/rk628_rgb.h +++ b/drivers/misc/rk628/rk628_rgb.h @@ -15,4 +15,5 @@ void rk628_rgb_tx_enable(struct rk628 *rk628); void rk628_rgb_tx_disable(struct rk628 *rk628); void rk628_bt1120_rx_enable(struct rk628 *rk628); void rk628_bt1120_tx_enable(struct rk628 *rk628); +void rk628_rgb_decoder_create_debugfs_file(struct rk628 *rk628); #endif