From 7d07b3ae8ddad407913c5301877e694430a3263f Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 23 Nov 2023 08:24:31 +0000
Subject: [PATCH] add build kerneldeb
---
kernel/drivers/gpu/drm/rockchip/rockchip_drm_tve.c | 509 +++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 443 insertions(+), 66 deletions(-)
diff --git a/kernel/drivers/gpu/drm/rockchip/rockchip_drm_tve.c b/kernel/drivers/gpu/drm/rockchip/rockchip_drm_tve.c
index 0a223dd..990b9cf 100644
--- a/kernel/drivers/gpu/drm/rockchip/rockchip_drm_tve.c
+++ b/kernel/drivers/gpu/drm/rockchip/rockchip_drm_tve.c
@@ -38,6 +38,76 @@
.vrefresh = 60, 0, },
};
+struct env_config {
+ u32 offset;
+ u32 value;
+};
+
+static struct env_config ntsc_bt656_config[] = {
+ { BT656_DECODER_CROP, 0x00000000 },
+ { BT656_DECODER_SIZE, 0x01e002d0 },
+ { BT656_DECODER_HTOTAL_HS_END, 0x035a003e },
+ { BT656_DECODER_VACT_ST_HACT_ST, 0x00160069 },
+ { BT656_DECODER_VTOTAL_VS_END, 0x020d0003 },
+ { BT656_DECODER_VS_ST_END_F1, 0x01060109 },
+ { BT656_DECODER_DBG_REG, 0x024002d0 },
+ { BT656_DECODER_CTRL, 0x00000009 },
+};
+
+static struct env_config ntsc_tve_config[] = {
+ { TVE_MODE_CTRL, 0x000af906 },
+ { TVE_HOR_TIMING1, 0x00c07a81 },
+ { TVE_HOR_TIMING2, 0x169810fc },
+ { TVE_HOR_TIMING3, 0x96b40000 },
+ { TVE_SUB_CAR_FRQ, 0x21f07bd7 },
+ { TVE_IMAGE_POSITION, 0x001500d6 },
+ { TVE_ROUTING, 0x10088880 },
+ { TVE_SYNC_ADJUST, 0x00000000 },
+ { TVE_STATUS, 0x00000000 },
+ { TVE_CTRL, 0x00000000 },
+ { TVE_INTR_STATUS, 0x00000000 },
+ { TVE_INTR_EN, 0x00000000 },
+ { TVE_INTR_CLR, 0x00000000 },
+ { TVE_COLOR_BUSRT_SAT, 0x0052543c },
+ { TVE_CHROMA_BANDWIDTH, 0x00000002 },
+ { TVE_BRIGHTNESS_CONTRAST, 0x00008300 },
+ { TVE_CLAMP, 0x00000000 },
+};
+
+static struct env_config pal_bt656_config[] = {
+ { BT656_DECODER_CROP, 0x00000000 },
+ { BT656_DECODER_SIZE, 0x024002d0 },
+ { BT656_DECODER_HTOTAL_HS_END, 0x0360003f },
+ { BT656_DECODER_VACT_ST_HACT_ST, 0x0016006f },
+ { BT656_DECODER_VTOTAL_VS_END, 0x02710003 },
+ { BT656_DECODER_VS_ST_END_F1, 0x0138013b },
+ { BT656_DECODER_DBG_REG, 0x024002d0 },
+ { BT656_DECODER_CTRL, 0x00000009 },
+};
+
+static struct env_config pal_tve_config[] = {
+ { TVE_MODE_CTRL, 0x010ab906 },
+ { TVE_HOR_TIMING1, 0x00c28381 },
+ { TVE_HOR_TIMING2, 0x267d111d },
+ { TVE_HOR_TIMING3, 0x66c00880 },
+ { TVE_SUB_CAR_FRQ, 0x2a098acb },
+ { TVE_IMAGE_POSITION, 0x001500f6 },
+ { TVE_ROUTING, 0x10008882 },
+ { TVE_SYNC_ADJUST, 0x00000000 },
+ { TVE_STATUS, 0x000000b0 },
+ { TVE_CTRL, 0x00000000 },
+ { TVE_INTR_STATUS, 0x00000000 },
+ { TVE_INTR_EN, 0x00000000 },
+ { TVE_INTR_CLR, 0x00000000 },
+ { TVE_COLOR_BUSRT_SAT, 0x00356245 },
+ { TVE_CHROMA_BANDWIDTH, 0x00000022 },
+ { TVE_BRIGHTNESS_CONTRAST, 0x0000aa00 },
+ { TVE_CLAMP, 0x00000000 },
+};
+
+#define BT656_ENV_CONFIG_SIZE (sizeof(ntsc_bt656_config) / sizeof(struct env_config))
+#define TVE_ENV_CONFIG_SIZE (sizeof(ntsc_tve_config) / sizeof(struct env_config))
+
#define tve_writel(offset, v) writel_relaxed(v, tve->regbase + (offset))
#define tve_readl(offset) readl_relaxed(tve->regbase + (offset))
@@ -54,6 +124,14 @@
int input_format;
int soc_type;
};
+
+static void tve_write_block(struct rockchip_tve *tve, struct env_config *config, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ tve_writel(config[i].offset, config[i].value);
+}
static int
rockchip_tve_get_modes(struct drm_connector *connector)
@@ -107,61 +185,106 @@
static void tve_set_mode(struct rockchip_tve *tve)
{
+ struct env_config *bt656_cfg, *tve_cfg;
int mode = tve->tv_format;
- dev_dbg(tve->dev, "tve set mode:%d\n", mode);
- if (tve->input_format == INPUT_FORMAT_RGB)
- tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
- v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
- v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(0));
- else
- tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
- v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
- v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(3));
+ if (tve->soc_type == SOC_RK3528) {
+ tve_writel(TVE_LUMA_FILTER1, tve->lumafilter0);
+ tve_writel(TVE_LUMA_FILTER2, tve->lumafilter1);
+ tve_writel(TVE_LUMA_FILTER3, tve->lumafilter2);
+ tve_writel(TVE_LUMA_FILTER4, tve->lumafilter3);
+ tve_writel(TVE_LUMA_FILTER5, tve->lumafilter4);
+ tve_writel(TVE_LUMA_FILTER6, tve->lumafilter5);
+ tve_writel(TVE_LUMA_FILTER7, tve->lumafilter6);
+ tve_writel(TVE_LUMA_FILTER8, tve->lumafilter7);
+ } else {
+ dev_dbg(tve->dev, "tve set mode:%d\n", mode);
+ if (tve->input_format == INPUT_FORMAT_RGB)
+ tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
+ v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
+ v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(0));
+ else
+ tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
+ v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
+ v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(3));
- tve_writel(TV_LUMA_FILTER0, tve->lumafilter0);
- tve_writel(TV_LUMA_FILTER1, tve->lumafilter1);
- tve_writel(TV_LUMA_FILTER2, tve->lumafilter2);
+ tve_writel(TV_LUMA_FILTER0, tve->lumafilter0);
+ tve_writel(TV_LUMA_FILTER1, tve->lumafilter1);
+ tve_writel(TV_LUMA_FILTER2, tve->lumafilter2);
+ }
if (mode == TVOUT_CVBS_NTSC) {
dev_dbg(tve->dev, "NTSC MODE\n");
- tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(1) |
- v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) |
- v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode));
- tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_NTSC) |
- v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
- tve_writel(TV_SATURATION, 0x0042543C);
- if (tve->test_mode)
- tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008300);
- else
- tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00007900);
- tve_writel(TV_FREQ_SC, 0x21F07BD7);
- tve_writel(TV_SYNC_TIMING, 0x00C07a81);
- tve_writel(TV_ADJ_TIMING, 0x96B40000 | 0x70);
- tve_writel(TV_ACT_ST, 0x001500D6);
- tve_writel(TV_ACT_TIMING, 0x069800FC | (1 << 12) | (1 << 28));
+ if (tve->soc_type == SOC_RK3528) {
+ bt656_cfg = ntsc_bt656_config;
+ tve_cfg = ntsc_tve_config;
+ tve_write_block(tve, bt656_cfg, BT656_ENV_CONFIG_SIZE);
+ tve_write_block(tve, tve_cfg, TVE_ENV_CONFIG_SIZE);
+ } else {
+ tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(1) |
+ v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) |
+ v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode));
+ tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_NTSC) |
+ v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
+ tve_writel(TV_SATURATION, 0x0042543C);
+ if (tve->test_mode)
+ tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008300);
+ else
+ tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00007900);
+
+ tve_writel(TV_FREQ_SC, 0x21F07BD7);
+ tve_writel(TV_SYNC_TIMING, 0x00C07a81);
+ tve_writel(TV_ADJ_TIMING, 0x96B40000 | 0x70);
+ tve_writel(TV_ACT_ST, 0x001500D6);
+ tve_writel(TV_ACT_TIMING, 0x069800FC | (1 << 12) | (1 << 28));
+ }
} else if (mode == TVOUT_CVBS_PAL) {
dev_dbg(tve->dev, "PAL MODE\n");
- tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(0) |
- v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) |
- v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode));
- tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_PAL) |
- v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
- tve_writel(TV_SATURATION, tve->saturation);
- tve_writel(TV_BRIGHTNESS_CONTRAST, tve->brightcontrast);
+ if (tve->soc_type == SOC_RK3528) {
+ bt656_cfg = pal_bt656_config;
+ tve_cfg = pal_tve_config;
- tve_writel(TV_FREQ_SC, 0x2A098ACB);
- tve_writel(TV_SYNC_TIMING, 0x00C28381);
- tve_writel(TV_ADJ_TIMING, (0xc << 28) | 0x06c00800 | 0x80);
- tve_writel(TV_ACT_ST, 0x001500F6);
- tve_writel(TV_ACT_TIMING, 0x0694011D | (1 << 12) | (2 << 28));
+ tve_write_block(tve, bt656_cfg, BT656_ENV_CONFIG_SIZE);
+ tve_write_block(tve, tve_cfg, TVE_ENV_CONFIG_SIZE);
+ } else {
+ tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(0) |
+ v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) |
+ v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode));
+ tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_PAL) |
+ v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
- tve_writel(TV_ADJ_TIMING, tve->adjtiming);
- tve_writel(TV_ACT_TIMING, 0x0694011D |
- (1 << 12) | (2 << 28));
+ tve_writel(TV_SATURATION, tve->saturation);
+ tve_writel(TV_BRIGHTNESS_CONTRAST, tve->brightcontrast);
+
+ tve_writel(TV_FREQ_SC, 0x2A098ACB);
+ tve_writel(TV_SYNC_TIMING, 0x00C28381);
+ tve_writel(TV_ADJ_TIMING, (0xc << 28) | 0x06c00800 | 0x80);
+ tve_writel(TV_ACT_ST, 0x001500F6);
+ tve_writel(TV_ACT_TIMING, 0x0694011D | (1 << 12) | (2 << 28));
+
+ tve_writel(TV_ADJ_TIMING, tve->adjtiming);
+ tve_writel(TV_ACT_TIMING, 0x0694011D | (1 << 12) | (2 << 28));
+ }
+ }
+
+ if (tve->soc_type == SOC_RK3528) {
+ u32 upsample_mode = 0;
+ u32 mask = 0;
+ u32 val = 0;
+ bool upsample_en;
+
+ upsample_en = tve->upsample_mode ? 1 : 0;
+ if (upsample_en)
+ upsample_mode = tve->upsample_mode - 1;
+ mask = m_TVE_DCLK_POL | m_TVE_DCLK_EN | m_DCLK_UPSAMPLE_2X4X |
+ m_DCLK_UPSAMPLE_EN | m_TVE_MODE | m_TVE_EN;
+ val = v_TVE_DCLK_POL(0) | v_TVE_DCLK_EN(1) | v_DCLK_UPSAMPLE_2X4X(upsample_mode) |
+ v_DCLK_UPSAMPLE_EN(upsample_en) | v_TVE_MODE(tve->tv_format) | v_TVE_EN(1);
+
+ tve_dac_grf_writel(RK3528_VO_GRF_CVBS_CON, (mask << 16) | val);
}
}
@@ -178,36 +301,57 @@
u32 mask = 0;
u32 val = 0;
u32 grfreg = 0;
+ u32 offset = 0;
if (enable) {
dev_dbg(tve->dev, "dac enable\n");
- mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN;
if (tve->soc_type == SOC_RK3036) {
+ mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN;
val = m_VBG_EN | m_DAC_EN | v_DAC_GAIN(tve->daclevel);
grfreg = RK3036_GRF_SOC_CON3;
} else if (tve->soc_type == SOC_RK312X) {
+ mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN;
val = m_VBG_EN | m_DAC_EN | v_DAC_GAIN(tve->daclevel);
grfreg = RK312X_GRF_TVE_CON;
} else if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) {
val = v_CUR_REG(tve->dac1level) | v_DR_PWR_DOWN(0) | v_BG_PWR_DOWN(0);
+ offset = VDAC_VDAC1;
+ } else if (tve->soc_type == SOC_RK3528) {
+ /*
+ * Reset the vdac
+ */
+ tve_dac_writel(VDAC_CLK_RST, v_ANALOG_RST(0) | v_DIGITAL_RST(0));
+ msleep(20);
+ tve_dac_writel(VDAC_CLK_RST, v_ANALOG_RST(1) | v_DIGITAL_RST(1));
+
+ tve_dac_writel(VDAC_CURRENT_CTRL, v_OUT_CURRENT(tve->vdac_out_current));
+
+ val = v_REF_VOLTAGE(7) | v_DAC_PWN(1) | v_BIAS_PWN(1);
+ offset = VDAC_PWM_REF_CTRL;
}
} else {
dev_dbg(tve->dev, "dac disable\n");
- mask = m_VBG_EN | m_DAC_EN;
- if (tve->soc_type == SOC_RK312X)
+ if (tve->soc_type == SOC_RK312X) {
+ mask = m_VBG_EN | m_DAC_EN;
grfreg = RK312X_GRF_TVE_CON;
- else if (tve->soc_type == SOC_RK3036)
+ } else if (tve->soc_type == SOC_RK3036) {
+ mask = m_VBG_EN | m_DAC_EN;
grfreg = RK3036_GRF_SOC_CON3;
- else if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328)
+ } else if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) {
val = v_CUR_REG(tve->dac1level) | m_DR_PWR_DOWN | m_BG_PWR_DOWN;
+ offset = VDAC_VDAC1;
+ } else if (tve->soc_type == SOC_RK3528) {
+ val = v_DAC_PWN(0) | v_BIAS_PWN(0);
+ offset = VDAC_PWM_REF_CTRL;
+ }
}
if (grfreg)
tve_dac_grf_writel(grfreg, (mask << 16) | val);
else if (tve->vdacbase)
- tve_dac_writel(VDAC_VDAC1, val);
+ tve_dac_writel(offset, val);
}
static int cvbs_set_disable(struct rockchip_tve *tve)
@@ -229,6 +373,18 @@
return 0;
}
+/*
+ * RK3528 supports bt656 to cvbs, and the others support rgb to cvbs.
+ *
+ * ┌──────────┐
+ * │ rgb data ├─────────────────────────────────────┐
+ * └──────────┘ │
+ * ▼
+ * ┌────────────┐ ┌───────────────┐ ┌───────────────────┐ ┌──────┐ ┌────────┐
+ * │ bt656 data ├───►│ bt656 decoder ├───►│ cvbs(tve) encoder ├───►│ vdac ├───►│ screen │
+ * └────────────┘ └───────────────┘ └───────────────────┘ └──────┘ └────────┘
+ *
+ */
static int cvbs_set_enable(struct rockchip_tve *tve)
{
int ret = 0;
@@ -242,8 +398,9 @@
dev_err(tve->dev, "failed to get pm runtime: %d\n", ret);
return ret;
}
- dac_enable(tve, true);
tve_set_mode(tve);
+ msleep(1000);
+ dac_enable(tve, true);
tve->enable = 1;
return 0;
@@ -264,6 +421,8 @@
static void rockchip_tve_encoder_disable(struct drm_encoder *encoder)
{
struct rockchip_tve *tve = encoder_to_tve(encoder);
+ struct drm_crtc *crtc = encoder->crtc;
+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
mutex_lock(&tve->suspend_lock);
@@ -271,6 +430,8 @@
cvbs_set_disable(tve);
mutex_unlock(&tve->suspend_lock);
+
+ s->output_if &= ~VOP_OUTPUT_IF_TV;
}
static void rockchip_tve_encoder_mode_set(struct drm_encoder *encoder,
@@ -309,6 +470,7 @@
struct drm_connector_state *conn_state)
{
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+ struct rockchip_tve *tve = encoder_to_tve(encoder);
struct drm_connector *connector = conn_state->connector;
struct drm_display_info *info = &connector->display_info;
@@ -319,6 +481,14 @@
else
s->bus_format = MEDIA_BUS_FMT_YUV8_1X24;
+ /*
+ * For RK3528:
+ * VOP -> BT656 output -> BT656 decoder -> TVE encoder -> CVBS output
+ */
+ if (tve->soc_type == SOC_RK3528)
+ s->output_if |= VOP_OUTPUT_IF_BT656;
+ else
+ s->output_if |= VOP_OUTPUT_IF_TV;
s->color_space = V4L2_COLORSPACE_SMPTE170M;
s->tv_state = &conn_state->tv;
@@ -354,8 +524,118 @@
.atomic_check = rockchip_tve_encoder_atomic_check,
};
-static int tve_parse_dt(struct device_node *np,
- struct rockchip_tve *tve)
+static int tve_read_otp_by_name(struct rockchip_tve *tve, char *name, u8 *val, u8 default_val)
+{
+ struct nvmem_cell *cell;
+ size_t len;
+ unsigned char *efuse_buf;
+ int ret = -EINVAL;
+
+ *val = default_val;
+ cell = nvmem_cell_get(tve->dev, name);
+ if (!IS_ERR(cell)) {
+ efuse_buf = nvmem_cell_read(cell, &len);
+ nvmem_cell_put(cell);
+ if (!IS_ERR(efuse_buf)) {
+ *val = efuse_buf[0];
+ kfree(efuse_buf);
+ return 0;
+ }
+ }
+
+ dev_err(tve->dev, "failed to read %s from otp, use default\n", name);
+
+ return ret;
+}
+
+static int tve_parse_dt(struct device_node *np, struct rockchip_tve *tve)
+{
+ int ret, val;
+ u8 out_current, version;
+
+ ret = of_property_read_u32(np, "rockchip,tvemode", &val);
+ if (ret < 0) {
+ tve->preferred_mode = 0;
+ } else if (val > 1) {
+ dev_err(tve->dev, "tve mode value invalid\n");
+ return -EINVAL;
+ }
+ tve->preferred_mode = val;
+
+ ret = of_property_read_u32(np, "rockchip,lumafilter0", &val);
+ if (val == 0 || ret < 0)
+ return -EINVAL;
+ tve->lumafilter0 = val;
+
+ ret = of_property_read_u32(np, "rockchip,lumafilter1", &val);
+ if (val == 0 || ret < 0)
+ return -EINVAL;
+ tve->lumafilter1 = val;
+
+ ret = of_property_read_u32(np, "rockchip,lumafilter2", &val);
+ if (val == 0 || ret < 0)
+ return -EINVAL;
+ tve->lumafilter2 = val;
+
+ ret = of_property_read_u32(np, "rockchip,lumafilter3", &val);
+ if (val == 0 || ret < 0)
+ return -EINVAL;
+ tve->lumafilter3 = val;
+
+ ret = of_property_read_u32(np, "rockchip,lumafilter4", &val);
+ if (val == 0 || ret < 0)
+ return -EINVAL;
+ tve->lumafilter4 = val;
+
+ ret = of_property_read_u32(np, "rockchip,lumafilter5", &val);
+ if (val == 0 || ret < 0)
+ return -EINVAL;
+ tve->lumafilter5 = val;
+
+ ret = of_property_read_u32(np, "rockchip,lumafilter6", &val);
+ if (val == 0 || ret < 0)
+ return -EINVAL;
+ tve->lumafilter6 = val;
+
+ ret = of_property_read_u32(np, "rockchip,lumafilter7", &val);
+ if (val == 0 || ret < 0)
+ return -EINVAL;
+ tve->lumafilter7 = val;
+
+ ret = of_property_read_u32(np, "rockchip,tve-upsample", &val);
+ if (val > DCLK_UPSAMPLEx4 || ret < 0)
+ return -EINVAL;
+ tve->upsample_mode = val;
+
+ /*
+ * Read vdac output current from OTP if exists, and the default
+ * current val is 0xd2.
+ */
+ ret = tve_read_otp_by_name(tve, "out-current", &out_current, 0xd2);
+ if (!ret) {
+ if (out_current) {
+ /*
+ * If test version is 0x0, the value of vdac out current
+ * needs to be reduced by one.
+ */
+ ret = tve_read_otp_by_name(tve, "version", &version, 0x0);
+ if (!ret) {
+ if (version == 0x0)
+ out_current -= 1;
+ }
+ } else {
+ /*
+ * If the current value read from OTP is 0, set it to default.
+ */
+ out_current = 0xd2;
+ }
+ }
+ tve->vdac_out_current = out_current;
+
+ return 0;
+}
+
+static int tve_parse_dt_legacy(struct device_node *np, struct rockchip_tve *tve)
{
int ret, val;
u32 getdac = 0;
@@ -441,9 +721,52 @@
return 0;
}
+static bool tve_check_lumafilter(struct rockchip_tve *tve)
+{
+ int lumafilter[8] = {INT_MAX};
+
+ /*
+ * The default lumafilter value is 0. If lumafilter value
+ * is equal to the dts value, uboot logo is enabled.
+ */
+ if (tve->soc_type == SOC_RK3528) {
+ lumafilter[0] = tve_readl(TVE_LUMA_FILTER1);
+ lumafilter[1] = tve_readl(TVE_LUMA_FILTER2);
+ lumafilter[2] = tve_readl(TVE_LUMA_FILTER3);
+ lumafilter[3] = tve_readl(TVE_LUMA_FILTER4);
+ lumafilter[4] = tve_readl(TVE_LUMA_FILTER5);
+ lumafilter[5] = tve_readl(TVE_LUMA_FILTER6);
+ lumafilter[6] = tve_readl(TVE_LUMA_FILTER7);
+ lumafilter[7] = tve_readl(TVE_LUMA_FILTER8);
+
+ if (lumafilter[0] == tve->lumafilter0 &&
+ lumafilter[1] == tve->lumafilter1 &&
+ lumafilter[2] == tve->lumafilter2 &&
+ lumafilter[3] == tve->lumafilter3 &&
+ lumafilter[4] == tve->lumafilter4 &&
+ lumafilter[5] == tve->lumafilter5 &&
+ lumafilter[6] == tve->lumafilter6 &&
+ lumafilter[7] == tve->lumafilter7) {
+ return true;
+ }
+ } else {
+ lumafilter[0] = tve_readl(TV_LUMA_FILTER0);
+ lumafilter[1] = tve_readl(TV_LUMA_FILTER1);
+ lumafilter[2] = tve_readl(TV_LUMA_FILTER2);
+
+ if (lumafilter[0] == tve->lumafilter0 &&
+ lumafilter[1] == tve->lumafilter1 &&
+ lumafilter[2] == tve->lumafilter2) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void check_uboot_logo(struct rockchip_tve *tve)
{
- int lumafilter0, lumafilter1, lumafilter2, vdac;
+ int vdac;
if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) {
vdac = tve_dac_readl(VDAC_VDAC1);
@@ -454,17 +777,7 @@
}
}
- lumafilter0 = tve_readl(TV_LUMA_FILTER0);
- lumafilter1 = tve_readl(TV_LUMA_FILTER1);
- lumafilter2 = tve_readl(TV_LUMA_FILTER2);
-
- /*
- * The default lumafilter value is 0. If lumafilter value
- * is equal to the dts value, uboot logo is enabled.
- */
- if (lumafilter0 == tve->lumafilter0 &&
- lumafilter1 == tve->lumafilter1 &&
- lumafilter2 == tve->lumafilter2) {
+ if (tve_check_lumafilter(tve)) {
tve->connector.dpms = DRM_MODE_DPMS_ON;
return;
}
@@ -495,11 +808,17 @@
.input_format = INPUT_FORMAT_YUV,
};
+static const struct rockchip_tve_data rk3528_tve = {
+ .soc_type = SOC_RK3528,
+ .input_format = INPUT_FORMAT_YUV,
+};
+
static const struct of_device_id rockchip_tve_dt_ids[] = {
{ .compatible = "rockchip,rk3036-tve", .data = &rk3036_tve },
{ .compatible = "rockchip,rk312x-tve", .data = &rk312x_tve },
{ .compatible = "rockchip,rk322x-tve", .data = &rk322x_tve },
{ .compatible = "rockchip,rk3328-tve", .data = &rk3328_tve },
+ { .compatible = "rockchip,rk3528-tve", .data = &rk3528_tve },
{}
};
@@ -536,14 +855,16 @@
tve->input_format = tve_data->input_format;
}
- ret = tve_parse_dt(np, tve);
+ if (tve->soc_type == SOC_RK3528)
+ ret = tve_parse_dt(np, tve);
+ else
+ ret = tve_parse_dt_legacy(np, tve);
if (ret) {
dev_err(tve->dev, "TVE parse dts error!");
return -EINVAL;
}
tve->enable = 0;
- platform_set_drvdata(pdev, tve);
tve->drm_dev = drm_dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
tve->reg_phy_base = res->start;
@@ -555,7 +876,8 @@
return PTR_ERR(tve->regbase);
}
- if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) {
+ if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328 ||
+ tve->soc_type == SOC_RK3528) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
tve->len = resource_size(res);
tve->vdacbase = devm_ioremap(tve->dev, res->start, tve->len);
@@ -576,6 +898,56 @@
if (ret) {
dev_err(tve->dev, "Cannot enable tve aclk: %d\n", ret);
return ret;
+ }
+ } else if (tve->soc_type == SOC_RK3528) {
+ tve->hclk = devm_clk_get(tve->dev, "hclk");
+ if (IS_ERR(tve->hclk)) {
+ dev_err(tve->dev, "Unable to get tve hclk\n");
+ return PTR_ERR(tve->hclk);
+ }
+
+ ret = clk_prepare_enable(tve->hclk);
+ if (ret) {
+ dev_err(tve->dev, "Cannot enable tve hclk: %d\n", ret);
+ return ret;
+ }
+
+ tve->pclk_vdac = devm_clk_get(tve->dev, "pclk_vdac");
+ if (IS_ERR(tve->pclk_vdac)) {
+ dev_err(tve->dev, "Unable to get vdac pclk\n");
+ return PTR_ERR(tve->pclk_vdac);
+ }
+
+ ret = clk_prepare_enable(tve->pclk_vdac);
+ if (ret) {
+ dev_err(tve->dev, "Cannot enable vdac pclk: %d\n", ret);
+ return ret;
+ }
+
+ tve->dclk = devm_clk_get(tve->dev, "dclk");
+ if (IS_ERR(tve->dclk)) {
+ dev_err(tve->dev, "Unable to get tve dclk\n");
+ return PTR_ERR(tve->dclk);
+ }
+
+ ret = clk_prepare_enable(tve->dclk);
+ if (ret) {
+ dev_err(tve->dev, "Cannot enable tve dclk: %d\n", ret);
+ return ret;
+ }
+
+ if (tve->upsample_mode == DCLK_UPSAMPLEx4) {
+ tve->dclk_4x = devm_clk_get(tve->dev, "dclk_4x");
+ if (IS_ERR(tve->dclk_4x)) {
+ dev_err(tve->dev, "Unable to get tve dclk_4x\n");
+ return PTR_ERR(tve->dclk_4x);
+ }
+
+ ret = clk_prepare_enable(tve->dclk_4x);
+ if (ret) {
+ dev_err(tve->dev, "Cannot enable tve dclk_4x: %d\n", ret);
+ return ret;
+ }
}
}
@@ -621,6 +993,7 @@
rockchip_drm_register_sub_dev(&tve->sub_dev);
pm_runtime_enable(dev);
+ dev_set_drvdata(dev, tve);
dev_dbg(tve->dev, "%s tv encoder probe ok\n", match->compatible);
return 0;
@@ -648,6 +1021,7 @@
drm_encoder_cleanup(&tve->encoder);
pm_runtime_disable(dev);
+ dev_set_drvdata(dev, NULL);
}
static const struct component_ops rockchip_tve_component_ops = {
@@ -666,6 +1040,9 @@
{
struct rockchip_tve *tve = dev_get_drvdata(&pdev->dev);
+ if (!tve)
+ return;
+
mutex_lock(&tve->suspend_lock);
dev_dbg(tve->dev, "tve shutdown\n");
--
Gitblit v1.6.2