From 4f584002d7e89978b6756a8475fce71f9c83c3c8 Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Sat, 9 Aug 2014 16:29:04 +0800 Subject: [PATCH] rk3128/rk3036 tve: 1. improve tve PAL format display parameter. 2. use static var rk3036_tve->screen instead of dynamicly malloc/free memory, to avoid kernel crash whicc is caused by NULL pointer. --- .../video/rockchip/tve/rk3036/rk3036_tve.c | 47 ++++++++++--------- .../video/rockchip/tve/rk3036/rk3036_tve.h | 8 +++- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/video/rockchip/tve/rk3036/rk3036_tve.c b/drivers/video/rockchip/tve/rk3036/rk3036_tve.c index 03c0cf91ef67..f9e06c634e52 100644 --- a/drivers/video/rockchip/tve/rk3036/rk3036_tve.c +++ b/drivers/video/rockchip/tve/rk3036/rk3036_tve.c @@ -21,13 +21,6 @@ #include #include "rk3036_tve.h" -#ifdef DEBUG -#define TVEDBG(format, ...) \ - printk(KERN_INFO "RK3036 TVE: " format "\n", ## __VA_ARGS__) -#else -#define TVEDBG(format, ...) -#endif - static const struct fb_videomode rk3036_cvbs_mode[] = { /*name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag*/ {"NTSC", 60, 720, 480, 27000000, 57, 19, 19, 0, 62, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0}, @@ -39,6 +32,13 @@ static struct rk3036_tve *rk3036_tve; #define tve_writel(offset, v) writel_relaxed(v, rk3036_tve->regbase + offset) #define tve_readl(offset) readl_relaxed(rk3036_tve->regbase + offset) +#ifdef DEBUG +#define TVEDBG(format, ...) \ + dev_info(rk3036_tve->dev, "RK3036 TVE: " format "\n", ## __VA_ARGS__) +#else +#define TVEDBG(format, ...) +#endif + static void dac_enable(bool enable) { u32 mask, val; @@ -46,14 +46,13 @@ static void dac_enable(bool enable) TVEDBG("%s enable %d\n", __func__, enable); if (enable) { - mask = m_VBG_EN | m_DAC_EN; - val = mask; + mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN; + val = m_VBG_EN | m_DAC_EN | v_DAC_GAIN(0x3b); } else { mask = m_VBG_EN | m_DAC_EN; val = 0; } grf_writel(rk3036_tve->grfreg, (mask << 16) | val); - grf_writel(RK312X_GRF_TVE_CON, (mask << 16) | val); } static void tve_set_mode(int mode) @@ -63,10 +62,15 @@ static void tve_set_mode(int mode) tve_writel(TV_RESET, v_RESET(1)); udelay(100); tve_writel(TV_RESET, v_RESET(0)); + if (rk3036_tve->inputformat == 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_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)); tve_writel(TV_LUMA_FILTER0, 0x02ff0000); tve_writel(TV_LUMA_FILTER1, 0xF40202fd); tve_writel(TV_LUMA_FILTER2, 0xF332d919); @@ -92,7 +96,7 @@ static void tve_set_mode(int mode) 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, 0x00325c40); + tve_writel(TV_SATURATION, /*0x00325c40*/ 0x00326346); tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008b00); tve_writel(TV_FREQ_SC, 0x2A098ACB); @@ -106,13 +110,10 @@ static void tve_set_mode(int mode) static int tve_switch_fb(const struct fb_videomode *modedb, int enable) { - struct rk_screen *screen; + struct rk_screen *screen = &rk3036_tve->screen; if (modedb == NULL) return -1; - screen = kzalloc(sizeof(screen), GFP_KERNEL); - if (screen == NULL) - return -1; memset(screen, 0, sizeof(struct rk_screen)); /* screen type & face */ @@ -148,7 +149,6 @@ static int tve_switch_fb(const struct fb_videomode *modedb, int enable) rk_fb_switch_screen(screen, enable, 0); - kfree(screen); if (enable) { if (screen->mode.yres == 480) tve_set_mode(TVOUT_CVBS_NTSC); @@ -208,7 +208,6 @@ cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode) if (rk3036_tve->enable && !rk3036_tve->suspend) dac_enable(false); tve_switch_fb(rk3036_tve->mode, 1); - msleep(500); dac_enable(true); } return 0; @@ -237,7 +236,7 @@ tve_fb_event_notify(struct notifier_block *self, case FB_BLANK_UNBLANK: break; default: - TVEDBG("suspend hdmi\n"); + TVEDBG("suspend tve\n"); if (!rk3036_tve->suspend) { rk3036_tve->suspend = 1; if (rk3036_tve->enable) { @@ -250,7 +249,7 @@ tve_fb_event_notify(struct notifier_block *self, } else if (action == FB_EVENT_BLANK) { switch (blank_mode) { case FB_BLANK_UNBLANK: - TVEDBG("resume hdmi\n"); + TVEDBG("resume tve\n"); if (rk3036_tve->suspend) { rk3036_tve->suspend = 0; if (rk3036_tve->enable) { @@ -323,8 +322,10 @@ static int rk3036_tve_probe(struct platform_device *pdev) if (!strcmp(match->compatible, "rockchip,rk3036-tve")) { rk3036_tve->grfreg = RK3036_GRF_SOC_CON3; + rk3036_tve->inputformat = INPUT_FORMAT_RGB; } else if (!strcmp(match->compatible, "rockchip,rk312x-tve")) { rk3036_tve->grfreg = RK312X_GRF_TVE_CON; + rk3036_tve->inputformat = INPUT_FORMAT_YUV; } else { dev_err(&pdev->dev, "It is not a valid tv encoder!"); kfree(rk3036_tve); @@ -352,7 +353,7 @@ static int rk3036_tve_probe(struct platform_device *pdev) rk_display_device_enable(rk3036_tve->ddev); fb_register_client(&tve_fb_notifier); - dev_info(&pdev->dev, "rk3036 tv encoder probe ok\n"); + dev_info(&pdev->dev, "%s tv encoder probe ok\n", match->compatible); return 0; } diff --git a/drivers/video/rockchip/tve/rk3036/rk3036_tve.h b/drivers/video/rockchip/tve/rk3036/rk3036_tve.h index c5cbf52c58c0..5d9e4eae9b7f 100644 --- a/drivers/video/rockchip/tve/rk3036/rk3036_tve.h +++ b/drivers/video/rockchip/tve/rk3036/rk3036_tve.h @@ -83,6 +83,11 @@ enum { TVOUT_CVBS_PAL, }; +enum { + INPUT_FORMAT_RGB = 0, + INPUT_FORMAT_YUV +}; + #define TVOUT_DEAULT TVOUT_CVBS_PAL #define grf_writel(offset, v) do { \ @@ -96,12 +101,13 @@ struct rk3036_tve { u32 reg_phy_base; u32 len; int grfreg; - + int inputformat; struct rk_display_device *ddev; unsigned int enable; unsigned int suspend; struct fb_videomode *mode; struct list_head modelist; + struct rk_screen screen; }; #endif \ No newline at end of file -- 2.34.1