From: Zheng Yang Date: Tue, 8 Jul 2014 10:11:59 +0000 (+0800) Subject: rk3036: add tv encoder code. X-Git-Tag: firefly_0821_release~4916^2~284 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;ds=sidebyside;h=b6d7152f51d613b4c16a83701416f45252b2e9e5;p=firefly-linux-kernel-4.4.55.git rk3036: add tv encoder code. --- diff --git a/arch/arm/boot/dts/rk3036-sdk.dts b/arch/arm/boot/dts/rk3036-sdk.dts index 38970e29a26f..a95b8a11d2b1 100755 --- a/arch/arm/boot/dts/rk3036-sdk.dts +++ b/arch/arm/boot/dts/rk3036-sdk.dts @@ -1,7 +1,8 @@ /dts-v1/; - +#include #include "rk3036.dtsi" #include "rk3036-pinctrl.dtsi" +#include "lcd-box.dtsi" / { fiq-debugger { @@ -137,3 +138,12 @@ //irq_gpio = <&gpio0 GPIO_A4 IRQ_TYPE_EDGE_FALLING>; }; }; + + +&rk_screen { + display-timings = <&disp_timings>; +}; + +&lcdc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 8aa9102a1e89..9da50489462e 100755 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -494,10 +494,19 @@ clock-names = "clk_usbphy1", "hclk_usb1"; }; + fb: fb{ + compatible = "rockchip,rk-fb"; + rockchip,disp-mode = ; + }; + + rk_screen: rk_screen{ + compatible = "rockchip,screen"; + }; + lcdc: lcdc@10118000 { compatible = "rockchip,rk3036-lcdc"; reg = <0x10118000 0x4000>; - interrupts = ; + interrupts = ; status = "disabled"; clocks = <&clk_gates9 6>, <&dclk_lcdc1>, <&clk_gates9 5>; clock-names = "aclk_lcdc", "dclk_lcdc", "hclk_lcdc"; @@ -517,6 +526,12 @@ status = "disabled"; }; + tve { + compatible = "rockchip,rk3036-tve"; + reg = <0x10118200 0x100>; + status = "disabled"; + }; + vpu: vpu_service@10108000 { compatible = "vpu_service"; reg = <0x10108000 0x800>; diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile index e03c30460300..03f76012b533 100755 --- a/drivers/video/rockchip/Makefile +++ b/drivers/video/rockchip/Makefile @@ -7,4 +7,6 @@ obj-$(CONFIG_ROCKCHIP_RGA) += rga/ obj-$(CONFIG_ROCKCHIP_RGA2) += rga2/ obj-$(CONFIG_RK_HDMI) += display-sys.o hdmi/ obj-$(CONFIG_IEP) += iep/ +obj-$(CONFIG_RK_TVENCODER) += tve/ + diff --git a/drivers/video/rockchip/lcdc/rk3036_lcdc.c b/drivers/video/rockchip/lcdc/rk3036_lcdc.c index e78ce2ea8c08..526b742a1f73 100644 --- a/drivers/video/rockchip/lcdc/rk3036_lcdc.c +++ b/drivers/video/rockchip/lcdc/rk3036_lcdc.c @@ -33,7 +33,10 @@ #include #include #include - +#if defined(CONFIG_ION_ROCKCHIP) +#include +#include +#endif #include "rk3036_lcdc.h" static int dbg_thresd; @@ -61,8 +64,6 @@ static struct rk_lcdc_win lcdc_win[] = { }, }; -static void layer_enable(struct lcdc_device *lcdc_dev, unsigned int win_id, bool open); - static irqreturn_t rk3036_lcdc_isr(int irq, void *dev_id) { struct lcdc_device *lcdc_dev = @@ -169,48 +170,100 @@ static void rk_lcdc_read_reg_defalut_cfg(struct lcdc_device spin_unlock(&lcdc_dev->reg_lock); } -/********do basic init*********/ -static int rk3036_lcdc_pre_init(struct rk_lcdc_driver *dev_drv) +static int rk3036_lcdc_alpha_cfg(struct lcdc_device *lcdc_dev) { - u32 mask,val; - struct lcdc_device *lcdc_dev = container_of(dev_drv, - struct - lcdc_device, - driver); - if (lcdc_dev->pre_init) - return 0; + return 0; +} - lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc"); - lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc"); - lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc"); -// lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc"); +static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev, struct rk_lcdc_win *win) { - if (/*IS_ERR(lcdc_dev->pd) ||*/ (IS_ERR(lcdc_dev->aclk)) || - (IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) { - dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n", - lcdc_dev->id); + u32 mask, val; + + if(win->state == 1){ + if(win->id == 0) { + mask = m_WIN0_EN | m_WIN0_FORMAT | m_WIN0_RB_SWAP; + val = v_WIN0_EN(win->state) | v_WIN0_FORMAT(win->fmt_cfg) | v_WIN0_RB_SWAP(win->swap_rb); + lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val); + + lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB, + v_X_SCL_FACTOR(win->scale_yrgb_x) | + v_Y_SCL_FACTOR(win->scale_yrgb_y)); + lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_CBR, + v_X_SCL_FACTOR(win->scale_cbcr_x) | + v_Y_SCL_FACTOR(win->scale_cbcr_y)); + + lcdc_msk_reg(lcdc_dev, WIN0_VIR, m_YRGB_VIR | m_CBBR_VIR, + v_YRGB_VIR(win->area[0].y_vir_stride) | v_YRGB_VIR(win->area[0].uv_vir_stride)); + lcdc_writel(lcdc_dev, WIN0_ACT_INFO, v_ACT_WIDTH(win->area[0].xact) | + v_ACT_HEIGHT(win->area[0].yact)); + lcdc_writel(lcdc_dev, WIN0_DSP_ST, v_DSP_STX(win->area[0].dsp_stx) | + v_DSP_STY(win->area[0].dsp_sty)); + lcdc_writel(lcdc_dev, WIN0_DSP_INFO, v_DSP_WIDTH(win->area[0].xsize) | + v_DSP_HEIGHT(win->area[0].ysize)); + + lcdc_writel(lcdc_dev, WIN0_YRGB_MST, win->area[0].y_addr); + lcdc_writel(lcdc_dev, WIN0_CBR_MST, win->area[0].uv_addr); + } + else if(win->id == 1) { + mask = m_WIN1_EN | m_WIN1_FORMAT | m_WIN1_RB_SWAP; + val = v_WIN1_EN(win->state) | v_WIN1_FORMAT(win->fmt_cfg) | v_WIN1_RB_SWAP(win->swap_rb); + lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val); + + lcdc_writel(lcdc_dev, WIN1_SCL_FACTOR_YRGB, + v_X_SCL_FACTOR(win->scale_yrgb_x) | + v_Y_SCL_FACTOR(win->scale_yrgb_y)); + + lcdc_msk_reg(lcdc_dev, WIN1_VIR, m_YRGB_VIR, v_YRGB_VIR(win->area[0].y_vir_stride)); + lcdc_writel(lcdc_dev, WIN1_ACT_INFO, v_ACT_WIDTH(win->area[0].xact) | + v_ACT_HEIGHT(win->area[0].yact)); + lcdc_writel(lcdc_dev, WIN1_DSP_INFO, v_DSP_WIDTH(win->area[0].xsize) | + v_DSP_HEIGHT(win->area[0].ysize)); + lcdc_writel(lcdc_dev, WIN1_DSP_ST, v_DSP_STX(win->area[0].dsp_stx) | + v_DSP_STY(win->area[0].dsp_sty)); + + lcdc_writel(lcdc_dev, WIN1_MST, win->area[0].y_addr); + + } + else if(win->id == 2) { + } + }else{ + win->area[0].y_addr = 0; + win->area[0].uv_addr = 0; + if(win->id == 0) { + lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN0_EN, v_WIN0_EN(0)); + } + else if(win->id == 1) + lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN1_EN, v_WIN1_EN(0)); + else if(win->id == 2) + lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_HWC_EN, v_HWC_EN(0)); } - - rk_disp_pwr_enable(dev_drv); - rk3036_lcdc_clk_enable(lcdc_dev); - - /*backup reg config at uboot*/ - rk_lcdc_read_reg_defalut_cfg(lcdc_dev); - - mask = m_AUTO_GATING_EN; - val = v_AUTO_GATING_EN(0); - lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask,val); - lcdc_cfg_done(lcdc_dev); - if (dev_drv->iommu_enabled) /*disable win0 to workaround iommu pagefault*/ - layer_enable(lcdc_dev, 0, 0); - lcdc_dev->pre_init = true; - - return 0; } -static int rk3036_lcdc_alpha_cfg(struct lcdc_device *lcdc_dev) +static void lcdc_layer_enable(struct lcdc_device *lcdc_dev, unsigned int win_id, bool open) { - return 0; + spin_lock(&lcdc_dev->reg_lock); + if (likely(lcdc_dev->clk_on) && lcdc_dev->driver.win[win_id]->state != open) { + if (open) { + if (!lcdc_dev->atv_layer_cnt) { + dev_info(lcdc_dev->dev, "wakeup from standby!\n"); + lcdc_dev->standby = 0; + } + lcdc_dev->atv_layer_cnt++; + } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) { + lcdc_dev->atv_layer_cnt--; + } + lcdc_dev->driver.win[win_id]->state = open; + if(!open) { + lcdc_layer_update_regs(lcdc_dev, lcdc_dev->driver.win[win_id]); + lcdc_cfg_done(lcdc_dev); + } + /*if no layer used,disable lcdc*/ + if (!lcdc_dev->atv_layer_cnt) { + dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n"); + lcdc_dev->standby = 1; + } + } + spin_unlock(&lcdc_dev->reg_lock); } static int rk3036_lcdc_reg_update(struct rk_lcdc_driver *dev_drv) @@ -225,37 +278,8 @@ static int rk3036_lcdc_reg_update(struct rk_lcdc_driver *dev_drv) if (likely(lcdc_dev->clk_on)) { lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY, v_LCDC_STANDBY(lcdc_dev->standby)); - lcdc_msk_reg(lcdc_dev, SYS_CTRL, - m_WIN0_EN | m_WIN1_EN | m_WIN0_RB_SWAP | - m_WIN1_RB_SWAP, - v_WIN0_EN(win0->state) | v_WIN1_EN(win1->state) | - v_WIN0_RB_SWAP(win0->swap_rb) | - v_WIN1_RB_SWAP(win1->swap_rb)); - lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB, - v_X_SCL_FACTOR(win0->scale_yrgb_x) | - v_Y_SCL_FACTOR(win0->scale_yrgb_y)); - lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_CBR, - v_X_SCL_FACTOR(win0->scale_cbcr_x) | - v_Y_SCL_FACTOR(win0->scale_cbcr_y)); - lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN0_FORMAT, v_WIN0_FORMAT(win0->fmt_cfg)); - lcdc_writel(lcdc_dev, WIN0_ACT_INFO, v_ACT_WIDTH(win0->area[0].xact) | - v_ACT_HEIGHT(win0->area[0].yact)); - lcdc_writel(lcdc_dev, WIN0_DSP_ST, v_DSP_STX(win0->area[0].dsp_stx) | - v_DSP_STY(win0->area[0].dsp_sty)); - lcdc_writel(lcdc_dev, WIN0_DSP_INFO, v_DSP_WIDTH(win0->area[0].xsize) | - v_DSP_HEIGHT(win0->area[0].ysize)); - lcdc_msk_reg(lcdc_dev, WIN0_VIR, m_YRGB_VIR | m_CBBR_VIR, - v_YRGB_VIR(win0->area[0].y_vir_stride) | v_YRGB_VIR(win0->area[0].uv_vir_stride)); - lcdc_writel(lcdc_dev, WIN0_YRGB_MST, win0->area[0].y_addr); - lcdc_writel(lcdc_dev, WIN0_CBR_MST, win0->area[0].uv_addr); - lcdc_writel(lcdc_dev, WIN1_DSP_INFO, v_DSP_WIDTH(win1->area[0].xsize) | - v_DSP_HEIGHT(win1->area[0].ysize)); - lcdc_writel(lcdc_dev, WIN1_DSP_ST, v_DSP_STX(win1->area[0].dsp_stx) | - v_DSP_STY(win1->area[0].dsp_sty)); - lcdc_msk_reg(lcdc_dev, WIN1_VIR, m_YRGB_VIR, v_YRGB_VIR(win1->area[0].y_vir_stride)); - lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN1_FORMAT, - v_WIN1_FORMAT(win1->fmt_cfg)); - lcdc_writel(lcdc_dev, WIN1_MST, win1->area[0].y_addr); + lcdc_layer_update_regs(lcdc_dev, win0); + lcdc_layer_update_regs(lcdc_dev, win1); rk3036_lcdc_alpha_cfg(lcdc_dev); lcdc_cfg_done(lcdc_dev); @@ -324,6 +348,39 @@ static int rk3036_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv) } +/********do basic init*********/ +static int rk3036_lcdc_pre_init(struct rk_lcdc_driver *dev_drv) +{ + struct lcdc_device *lcdc_dev = container_of(dev_drv, + struct lcdc_device, driver); + if (lcdc_dev->pre_init) + return 0; + + lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc"); + lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc"); + lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc"); +// lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc"); + + if (/*IS_ERR(lcdc_dev->pd) ||*/ (IS_ERR(lcdc_dev->aclk)) || + (IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) { + dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n", + lcdc_dev->id); + } + + rk_disp_pwr_enable(dev_drv); + rk3036_lcdc_clk_enable(lcdc_dev); + + /*backup reg config at uboot*/ + rk_lcdc_read_reg_defalut_cfg(lcdc_dev); + lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_AUTO_GATING_EN,v_AUTO_GATING_EN(0)); + lcdc_cfg_done(lcdc_dev); + if (dev_drv->iommu_enabled) /*disable win0 to workaround iommu pagefault*/ + lcdc_layer_enable(lcdc_dev, 0, 0); + lcdc_dev->pre_init = true; + + return 0; +} + static int rk3036_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) { int ret = -EINVAL; @@ -360,6 +417,14 @@ static int rk3036_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) val |= v_CORE_CLK_DIV_EN(1); } lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val); + if(x_res == 720 && y_res == 576) + lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_TVE_MODE, v_TVE_MODE(TV_PAL)); + else if(x_res == 720 && y_res == 480) + lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_TVE_MODE, v_TVE_MODE(TV_NTSC)); + else { + dev_err(lcdc_dev->dev, "unsupported video timing!\n"); + return -1; + } break; default: dev_err(lcdc_dev->dev, "un supported interface!\n"); @@ -396,17 +461,34 @@ static int rk3036_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) v_HASP(screen->mode.hsync_len + left_margin); lcdc_writel(lcdc_dev, DSP_HACT_ST_END, val); - val = - v_VSYNC(screen->mode.vsync_len) | v_VERPRD(screen->mode. - vsync_len + - upper_margin + - y_res + - lower_margin); - lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END, val); - - val = v_VAEP(screen->mode.vsync_len + upper_margin + y_res) | - v_VASP(screen->mode.vsync_len + screen->mode.upper_margin); - lcdc_writel(lcdc_dev, DSP_VACT_ST_END, val); + if(screen->mode.vmode == FB_VMODE_INTERLACED) { + //First Field Timing + lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END, v_VSYNC(screen->mode.vsync_len) | + v_VERPRD(2 * (screen->mode.vsync_len + upper_margin + lower_margin) + y_res + 1)); + lcdc_writel(lcdc_dev,DSP_VACT_ST_END,v_VAEP(screen->mode.vsync_len + upper_margin + y_res/2)| + v_VASP(screen->mode.vsync_len + upper_margin)); + //Second Field Timing + lcdc_writel(lcdc_dev, DSP_VS_ST_END_F1, v_VSYNC_ST_F1(screen->mode.vsync_len + upper_margin + y_res/2 + lower_margin) | + v_VSYNC_END_F1(2 * screen->mode.vsync_len + upper_margin + y_res/2 + lower_margin)); + lcdc_writel(lcdc_dev,DSP_VACT_ST_END_F1,v_VAEP(2 * (screen->mode.vsync_len + upper_margin) + y_res + lower_margin + 1)| + v_VASP(2 * (screen->mode.vsync_len + upper_margin) + y_res/2 + lower_margin + 1)); + + lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_INTERLACE_DSP_EN | m_WIN1_INTERLACE_EN | m_WIN0_YRGB_DEFLICK_EN | m_WIN0_CBR_DEFLICK_EN, + v_INTERLACE_DSP_EN(1) | v_WIN1_INTERLACE_EN(1) | v_WIN0_YRGB_DEFLICK_EN(1) | v_WIN0_CBR_DEFLICK_EN(1) ); + } else { + val = v_VSYNC(screen->mode.vsync_len) | + v_VERPRD(screen->mode.vsync_len + upper_margin + + y_res + lower_margin); + lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END, val); + + val = v_VAEP(screen->mode.vsync_len + upper_margin + y_res) | + v_VASP(screen->mode.vsync_len + screen->mode.upper_margin); + lcdc_writel(lcdc_dev, DSP_VACT_ST_END, val); + + lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_INTERLACE_DSP_EN | m_WIN1_INTERLACE_EN | m_WIN0_YRGB_DEFLICK_EN | m_WIN0_CBR_DEFLICK_EN, + v_INTERLACE_DSP_EN(0) | v_WIN1_INTERLACE_EN(0) | v_WIN0_YRGB_DEFLICK_EN(0) | v_WIN0_CBR_DEFLICK_EN(0) ); + } + } spin_unlock(&lcdc_dev->reg_lock); @@ -429,35 +511,6 @@ static int rk3036_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) return 0; } -static void layer_enable(struct lcdc_device *lcdc_dev, unsigned int win_id, bool open) -{ - spin_lock(&lcdc_dev->reg_lock); - if (likely(lcdc_dev->clk_on)) { - if (open) { - if (!lcdc_dev->atv_layer_cnt) { - dev_info(lcdc_dev->dev, "wakeup from standby!\n"); - lcdc_dev->standby = 0; - } - lcdc_dev->atv_layer_cnt++; - } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) { - lcdc_dev->atv_layer_cnt--; - } - lcdc_dev->driver.win[win_id]->state = open; - if(win_id == 0) - lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN0_EN, v_WIN0_EN(open)); - else if(win_id == 1) - lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN1_EN, v_WIN1_EN(open)); - else - lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_HWC_EN, v_HWC_EN(open)); - /*if no layer used,disable lcdc*/ - if (!lcdc_dev->atv_layer_cnt) { - dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n"); - lcdc_dev->standby = 1; - } - } - spin_unlock(&lcdc_dev->reg_lock); -} - static int rk3036_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id, bool open) { @@ -468,6 +521,20 @@ static int rk3036_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id, if ((open) && (!lcdc_dev->atv_layer_cnt)) { rk3036_lcdc_pre_init(dev_drv); rk3036_lcdc_clk_enable(lcdc_dev); + #if defined(CONFIG_ROCKCHIP_IOMMU) + if(dev_drv->iommu_enabled) { + if(!dev_drv->mmu_dev) { + dev_drv->mmu_dev = rockchip_get_sysmmu_device_by_compatible(dev_drv->mmu_dts_name); + if (dev_drv->mmu_dev) + platform_set_sysmmu(dev_drv->mmu_dev, dev_drv->dev); + else { + dev_err(dev_drv->dev, "failed to get rockchip iommu device\n"); + return -1; + } + } + iovmm_activate(dev_drv->dev); + } + #endif rk3036_lcdc_reg_restore(lcdc_dev); if (dev_drv->iommu_enabled) rk3036_lcdc_mmu_en(dev_drv); @@ -478,8 +545,9 @@ static int rk3036_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id, rk3036_load_screen(dev_drv, 1); } } + if(win_id < ARRAY_SIZE(lcdc_win)) { - layer_enable(lcdc_dev, win_id, open); + lcdc_layer_enable(lcdc_dev, win_id, open); } else dev_err(lcdc_dev->dev, "invalid win id:%d\n", win_id); @@ -488,6 +556,14 @@ static int rk3036_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id, if ((!open) && (!lcdc_dev->atv_layer_cnt)) { rk3036_lcdc_disable_irq(lcdc_dev); rk3036_lcdc_reg_update(dev_drv); + #if defined(CONFIG_ROCKCHIP_IOMMU) + if (dev_drv->iommu_enabled) { +// for (reg = MMU_DTE_ADDR; reg <= MMU_AUTO_GATING; reg +=4) +// lcdc_readl(lcdc_dev, reg); + if(dev_drv->mmu_dev) + iovmm_deactivate(dev_drv->dev); + } + #endif rk3036_lcdc_clk_disable(lcdc_dev); } @@ -517,9 +593,13 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv,int win_id) } spin_lock(&lcdc_dev->reg_lock); - win->area[0].dsp_stx = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len; - win->area[0].dsp_sty = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len; + if (screen->mode.vmode == FB_VMODE_INTERLACED) { + win->area[0].ysize /= 2; + win->area[0].dsp_sty = win->area[0].ypos/2+screen->mode.upper_margin + screen->mode.vsync_len; + } else { + win->area[0].dsp_sty = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len; + } win->scale_yrgb_x = CalScale(win->area[0].xact, win->area[0].xsize); win->scale_yrgb_y = CalScale(win->area[0].yact, win->area[0].ysize); switch (win->format) { @@ -584,9 +664,6 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv,int win_id) } spin_unlock(&lcdc_dev->reg_lock); - if (lcdc_dev->clk_on) { - rk3036_lcdc_alpha_cfg(lcdc_dev); - } DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n" ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id, __func__, get_format_string(win->format, fmt), win->area[0].xact, @@ -621,11 +698,8 @@ static int rk3036_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id) if (likely(lcdc_dev->clk_on)) { win->area[0].y_addr = win->area[0].smem_start+win->area[0].y_offset; win->area[0].uv_addr = win->area[0].cbr_start + win->area[0].c_offset; - if(win_id == 0) { - lcdc_writel(lcdc_dev, WIN0_YRGB_MST, win->area[0].y_addr); - lcdc_writel(lcdc_dev, WIN0_CBR_MST, win->area[0].uv_addr); - } else - lcdc_writel(lcdc_dev, WIN1_MST, win->area[0].y_addr); + if(win->area[0].y_addr) + lcdc_layer_update_regs(lcdc_dev, win); /*lcdc_cfg_done(lcdc_dev);*/ } spin_unlock(&lcdc_dev->reg_lock); @@ -741,6 +815,14 @@ static int rk3036_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv) lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY, v_LCDC_STANDBY(1)); lcdc_cfg_done(lcdc_dev); + #if defined(CONFIG_ROCKCHIP_IOMMU) + if (dev_drv->iommu_enabled) { +// for (reg = MMU_DTE_ADDR; reg <= MMU_AUTO_GATING; reg +=4) +// lcdc_readl(lcdc_dev, reg); + if(dev_drv->mmu_dev) + iovmm_deactivate(dev_drv->dev); + } + #endif spin_unlock(&lcdc_dev->reg_lock); } else { spin_unlock(&lcdc_dev->reg_lock); @@ -970,7 +1052,7 @@ static int rk3036_fb_win_remap(struct rk_lcdc_driver *dev_drv, { mutex_lock(&dev_drv->fb_win_id_mutex); if (order == FB_DEFAULT_ORDER) - order = FB0_WIN0_FB1_WIN1_FB2_WIN2; + order = FB0_WIN1_FB1_WIN0_FB2_WIN2; dev_drv->fb2_win_id = order / 100; dev_drv->fb1_win_id = (order / 10) % 10; dev_drv->fb0_win_id = order % 10; @@ -1125,6 +1207,22 @@ static struct rk_lcdc_drv_ops lcdc_drv_ops = { .open_bcsh = rk3036_lcdc_open_bcsh, }; +static int rk3036_lcdc_parse_dt(struct lcdc_device *lcdc_dev) +{ + struct device_node *np = lcdc_dev->dev->of_node; + +#if defined(CONFIG_ROCKCHIP_IOMMU) + int val; + if (of_property_read_u32(np, "rockchip,iommu-enabled", &val)) + lcdc_dev->driver.iommu_enabled = 0; + else + lcdc_dev->driver.iommu_enabled = val; +#else + lcdc_dev->driver.iommu_enabled = 0; +#endif + return 0; +} + static int rk3036_lcdc_probe(struct platform_device *pdev) { struct lcdc_device *lcdc_dev = NULL; @@ -1141,6 +1239,7 @@ static int rk3036_lcdc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, lcdc_dev); lcdc_dev->dev = dev; + rk3036_lcdc_parse_dt(lcdc_dev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); lcdc_dev->reg_phy_base = res->start; @@ -1176,7 +1275,11 @@ static int rk3036_lcdc_probe(struct platform_device *pdev) lcdc_dev->irq, ret); return ret; } - + + if (dev_drv->iommu_enabled) { + strcpy(dev_drv->mmu_dts_name, "iommu,vop_mmu"); + } + ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id); if (ret < 0) { dev_err(dev, "register fb for lcdc%d failed!\n", lcdc_dev->id); @@ -1184,7 +1287,9 @@ static int rk3036_lcdc_probe(struct platform_device *pdev) } lcdc_dev->screen = dev_drv->screen0; - dev_info(dev, "lcdc%d probe ok\n", lcdc_dev->id); + dev_info(dev, "lcdc%d probe ok, iommu %s\n", + lcdc_dev->id, dev_drv->iommu_enabled ? "enabled" : "disabled"); + return 0; } diff --git a/drivers/video/rockchip/lcdc/rk3036_lcdc.h b/drivers/video/rockchip/lcdc/rk3036_lcdc.h index bb0861ac8e01..9c37f9b7a285 100644 --- a/drivers/video/rockchip/lcdc/rk3036_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk3036_lcdc.h @@ -252,6 +252,8 @@ #define v_VASP(x) (((x)&0xfff)<<16) #define DSP_VS_ST_END_F1 (0x7C) + #define v_VSYNC_END_F1(x) (((x)&0xfff)<<0) + #define v_VSYNC_ST_F1(x) (((x)&0xfff)<<16) #define DSP_VACT_ST_END_F1 (0x80) /*BCSH Registers*/ @@ -342,7 +344,7 @@ #define REG_CFG_DONE (0x90) /* TV Control Registers */ -#define TV_CTRL (0x200) +#define TV_CTRL (0x200) #define TV_SYNC_TIMING (0x204) #define TV_ACT_TIMING (0x208) #define TV_ADJ_TIMING (0x20c) @@ -484,7 +486,7 @@ struct lcdc_device{ struct clk *aclk; /*lcdc share memory frequency*/ u32 pixclock; - u32 standby; /*1:standby,0:wrok*/ + u32 standby; /*1:standby,0:work*/ }; static inline void lcdc_writel(struct lcdc_device *lcdc_dev,u32 offset,u32 v) diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index bf7e6ccf35ca..e6d061fface2 100755 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -378,7 +378,7 @@ int rk_fb_prase_timing_dt(struct device_node *np, struct rk_screen *screen) pr_err("parse display timing err\n"); return -EINVAL; } - dt = display_timings_get(disp_timing, 0); + dt = display_timings_get(disp_timing, disp_timing->native_mode); rk_fb_video_mode_from_timing(dt, screen); return 0; @@ -2467,6 +2467,7 @@ static int rk_fb_set_par(struct fb_info *info) struct rk_lcdc_win *extend_win = NULL; struct rk_lcdc_win *win = NULL; struct rk_screen *screen = dev_drv->cur_screen; + struct rk_screen screen_primary; int win_id = 0; u32 cblen = 0, crlen = 0; u16 xsize = 0, ysize = 0; /* winx display window height/width --->LCDC_WINx_DSP_INFO */ @@ -2619,23 +2620,23 @@ static int rk_fb_set_par(struct fb_info *info) } } + rk_fb_get_prmry_screen(&screen_primary); win->format = fb_data_fmt; win->area[0].y_vir_stride = stride >> 2; win->area[0].uv_vir_stride = uv_stride >> 2; - win->area[0].xpos = xpos; - win->area[0].ypos = ypos; - win->area[0].xsize = xsize; - win->area[0].ysize = ysize; + win->area[0].xpos = xpos*screen->mode.xres/screen_primary.mode.xres; + win->area[0].ypos = ypos*screen->mode.yres/screen_primary.mode.yres; + win->area[0].xsize = screen->mode.xres*xsize/screen_primary.mode.xres; + win->area[0].ysize = screen->mode.yres*ysize/screen_primary.mode.yres; - win->area[0].smem_start = fix->smem_start; - win->area[0].cbr_start = fix->smem_start + stride * yvir; /* fix->mmio_start; */ +// win->area[0].smem_start = fix->smem_start; +// win->area[0].cbr_start = fix->smem_start+stride*yvir;//fix->mmio_start; win->area[0].xact = var->xres; /* winx active window height,is a wint of vir */ win->area[0].yact = var->yres; win->area[0].xvir = var->xres_virtual; /* virtual resolution stride --->LCDC_WINx_VIR */ win->area[0].yvir = var->yres_virtual; - win->area[0].state = 1; + win->area_num = 1; - win->state = 1; win->alpha_mode = 4; /* AB_SRC_OVER; */ win->alpha_en = ((win->format == ARGB888) || (win->format == ABGR888)) ? 1 : 0; @@ -2851,7 +2852,7 @@ void rk_direct_fb_show(struct fb_info *fbi) rk_fb_pan_display(&fbi->var, fbi); } EXPORT_SYMBOL(rk_direct_fb_show); - +#if 0 static int set_xact_yact_for_hdmi(struct fb_var_screeninfo *pmy_var, struct fb_var_screeninfo *hdmi_var) { @@ -2868,7 +2869,7 @@ static int set_xact_yact_for_hdmi(struct fb_var_screeninfo *pmy_var, return 0; } - +#endif int rk_fb_dpi_open(bool open) { struct rk_lcdc_driver *dev_drv = NULL; @@ -2899,7 +2900,109 @@ int rk_fb_dpi_status(void) return ret; } +#if 1 +/* + *function:this function will be called by display device, enable/disable lcdc + *screen: screen timing to be set to lcdc + *enable: 0 disable lcdc; 1 enable change lcdc timing; 2 just enable dclk + *lcdc_id: the lcdc id the display device attached ,0 or 1 + */ +int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) +{ + struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev); + struct fb_info *info = NULL; + struct rk_lcdc_driver *dev_drv = NULL; + char name[6]; + int i, win_id; + + if(screen == NULL) + return -ENODEV; + + printk("\n%s lcdc_id %d type %d enable %d\n", __FUNCTION__, lcdc_id, screen->type, enable); + + sprintf(name, "lcdc%d",lcdc_id); + for(i = 0; i < rk_fb->num_lcdc; i++) { + if(!strcmp(rk_fb->lcdc_dev_drv[i]->name, name)) { + dev_drv = rk_fb->lcdc_dev_drv[i]; + break; + } + } + if(i == rk_fb->num_lcdc) { + printk(KERN_ERR "%s driver not found!", name); + return -ENODEV; + } + + if(enable == 2 /*&& dev_drv->enable*/) + return 0; + + if(!enable) + { + // if screen type is different, we do not disable lcdc. + if( dev_drv->cur_screen->type != screen->type ) + return 0; + + for(i = 0; i < dev_drv->lcdc_win_num; i++) { + //disable the layer which attached to this device + if(dev_drv->win[i] && dev_drv->win[i]->state) + dev_drv->ops->open(dev_drv, i, 0); + } + +// dev_drv->enable = enable; + return 0; + } + else + memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen)); + +// dev_drv->enable = enable; + +// ret = dev_drv->ops->load_screen(dev_drv, 1); +// +// if(enable != 1) return 0; + + for(i = 0; i < dev_drv->lcdc_win_num; i++) { + #ifdef DUAL_LCDC_MAP_TO_SAME_FB + info = rk_fb->fb[i]; + dev_drv1 = (struct rk_lcdc_driver *)info->par; + if(dev_drv1 != dev_drv) { + info->par = dev_drv; +// dev_drv->overlay = dev_drv1->overlay; + dev_drv->overscan = dev_drv1->overscan; + dev_drv->vsync_info.active = dev_drv1->vsync_info.active; + } + memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen)); + #else + info = rk_fb->fb[dev_drv->fb_index_base + i]; + #endif + win_id = dev_drv->ops->fb_get_win_id(dev_drv,info->fix.id); +// printk("%s win id %d\n", info->fix.id, win_id); + if(dev_drv->win[win_id]) { + #ifdef DUAL_LCDC_MAP_TO_SAME_FB + if(dev_drv1 && dev_drv1->win[win_id]) { + dev_drv->win[win_id]->logicalstate = dev_drv1->win[win_id]->logicalstate; + memcpy(dev_drv->win[win_id]->area, dev_drv1->win[win_id]->area, RK_WIN_MAX_AREA * sizeof(struct rk_lcdc_win_area)); +// dev_drv->win[win_id]->area[0] = dev_drv1->win[win_id]->area[0]; +// printk("%s win id %d state %d\n", info->fix.id, win_id, dev_drv->win[win_id]->logicalstate); + } + #endif + printk("%s win id %d state %d\n", info->fix.id, win_id, dev_drv->win[win_id]->logicalstate); + if( dev_drv->win[win_id]->logicalstate ) { + dev_drv->ops->open(dev_drv, win_id, 1); + if(win_id == 1) { + dev_drv->ops->load_screen(dev_drv, 1); + } + info->var.activate |= FB_ACTIVATE_FORCE; + info->fbops->fb_set_par(info); + info->fbops->fb_pan_display(&info->var, info); + } +// else +// dev_drv->ops->open(dev_drv, win_id, 0); + } + } + printk("\n%s lcdc_id %d type %d enable %d done\n\n", __FUNCTION__, lcdc_id, screen->type, enable); + return 0; +} +#else /* * function:this function will be called by hdmi,when * hdmi plug in/out @@ -3043,7 +3146,7 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) return 0; } - +#endif /* * function:this function current only called by hdmi for * scale the display @@ -3326,12 +3429,17 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb, mutex_init(&dev_drv->fb_win_id_mutex); dev_drv->ops->fb_win_remap(dev_drv, FB_DEFAULT_ORDER); dev_drv->first_frame = 1; + dev_drv->overscan.left = 100; + dev_drv->overscan.top = 100; + dev_drv->overscan.right = 100; + dev_drv->overscan.bottom = 100; rk_disp_pwr_ctr_parse_dt(dev_drv); if (dev_drv->prop == PRMRY) { - dev_drv->ops->set_dsp_cabc(dev_drv, dev_drv->cabc_mode); + if(dev_drv->ops->set_dsp_cabc) + dev_drv->ops->set_dsp_cabc(dev_drv, dev_drv->cabc_mode); rk_fb_set_prmry_screen(screen); - rk_fb_get_prmry_screen(screen); } + rk_fb_get_prmry_screen(screen); dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type); return 0; @@ -3384,9 +3492,9 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv, struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev); struct fb_info *fbi; int i = 0, ret = 0, index = 0; -#if defined(CONFIG_ROCKCHIP_IOMMU) - struct device *mmu_dev = NULL; -#endif +//#if defined(CONFIG_ROCKCHIP_IOMMU) +// struct device *mmu_dev = NULL; +//#endif if (rk_fb->num_lcdc == RK30_MAX_LCDC_SUPPORT) return -ENXIO; @@ -3491,6 +3599,7 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv, if (dev_drv->prop == PRMRY) { struct fb_info *main_fbi = rk_fb->fb[0]; main_fbi->fbops->fb_open(main_fbi, 1); +/* #if defined(CONFIG_ROCKCHIP_IOMMU) if (dev_drv->iommu_enabled) { mmu_dev = @@ -3505,6 +3614,7 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv, "failed to get rockchip iommu device\n"); } #endif +*/ rk_fb_alloc_buffer(main_fbi, 0); /* only alloc memory for main fb */ if (support_uboot_display()) { if (dev_drv->iommu_enabled) { diff --git a/drivers/video/rockchip/tve/Kconfig b/drivers/video/rockchip/tve/Kconfig index 74eaf28651be..e165ee3250ef 100644 --- a/drivers/video/rockchip/tve/Kconfig +++ b/drivers/video/rockchip/tve/Kconfig @@ -1,14 +1,13 @@ -config RK610_TVOUT - bool "RK610(Jetta) tvout support" - depends on MFD_RK610 - default n +# +# TV Encoder drivers configuration +# + +menuconfig RK_TVENCODER + bool "Rockchip TV Encoder support" + depends on FB_ROCKCHIP help - Support Jetta(RK610) to output YPbPr and CVBS. - -config RK610_TVOUT_YPbPr - bool "support YPbPr output" - depends on RK610_TVOUT + Support RockChip TV Encoder if you say y here. + +source "drivers/video/rockchip/tve/rk3036/Kconfig" +source "drivers/video/rockchip/tve/rk610/Kconfig" -config RK610_TVOUT_CVBS - bool "support CVBS output" - depends on RK610_TVOUT diff --git a/drivers/video/rockchip/tve/Makefile b/drivers/video/rockchip/tve/Makefile index b7d457326d26..ea651687c417 100644 --- a/drivers/video/rockchip/tve/Makefile +++ b/drivers/video/rockchip/tve/Makefile @@ -1,6 +1,5 @@ # -# Makefile for the jetta tv control. +# Makefile for tv encoder. # -obj-$(CONFIG_RK610_TVOUT) += rk610_tv.o -obj-$(CONFIG_RK610_TVOUT_YPbPr) += rk610_tv_ypbpr.o -obj-$(CONFIG_RK610_TVOUT_CVBS) += rk610_tv_cvbs.o \ No newline at end of file +obj-$(CONFIG_RK610_TVOUT) += rk610/ +obj-$(CONFIG_RK3036_TV_ENCODER) += rk3036/ diff --git a/drivers/video/rockchip/tve/rk3036/Kconfig b/drivers/video/rockchip/tve/rk3036/Kconfig new file mode 100644 index 000000000000..c39ed5d6dabd --- /dev/null +++ b/drivers/video/rockchip/tve/rk3036/Kconfig @@ -0,0 +1,7 @@ +config RK3036_TV_ENCODER + bool "rk3036 tv encoder support" + depends on LCDC_RK3036 + default n + help + Support RK3036 output CVBS. + diff --git a/drivers/video/rockchip/tve/rk3036/Makefile b/drivers/video/rockchip/tve/rk3036/Makefile new file mode 100644 index 000000000000..850404a1bdd3 --- /dev/null +++ b/drivers/video/rockchip/tve/rk3036/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for the rk3036 tv encoder control. +# +obj-$(CONFIG_RK3036_TV_ENCODER) += rk3036_tve.o diff --git a/drivers/video/rockchip/tve/rk3036/rk3036_tve.c b/drivers/video/rockchip/tve/rk3036/rk3036_tve.c new file mode 100644 index 000000000000..ebe29da48406 --- /dev/null +++ b/drivers/video/rockchip/tve/rk3036/rk3036_tve.c @@ -0,0 +1,305 @@ +/* + * rk3036_tve.c + * + * Driver for rockchip rk3036 tv encoder control + * Copyright (C) 2014 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "rk3036_tve.h" + + +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, 69, 12, 19, 2, 63, 3, 0, FB_VMODE_INTERLACED, 0}, + { "PAL", 50, 720, 576, 27000000, 57, 19, 19, 0, 62, 3, 0, FB_VMODE_INTERLACED, 0}, +}; + +static struct rk3036_tve *rk3036_tve = NULL; + +#define tve_writel(offset, v) writel_relaxed(v, rk3036_tve->regbase + offset); +#define tve_readl(offset, v) readl_relaxed(v, rk3036_tve->regbase + offset); + +static void dac_enable(bool enable) +{ + u32 mask, val; + if(enable) { + mask = m_VBG_EN | m_DAC_EN; + val = mask; + } else { + mask = m_VBG_EN | m_DAC_EN; + val = 0; + } + grf_writel(RK3036_GRF_SOC_CON3, (mask << 16) | val); +} + +static void tve_set_mode (int mode) +{ + tve_writel(TV_RESET, v_RESET(1)); + udelay(100); + tve_writel(TV_RESET, v_RESET(0)); + + 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); + + if(mode == TVOUT_CVBS_NTSC) { + tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(0) | + v_Y_AGC_PULSE_ON(1) | v_Y_VIDEO_ON(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, 0x0052543C); + tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008300); + + tve_writel(TV_FREQ_SC, 0x21F07BD7); + tve_writel(TV_SYNC_TIMING, 0x00C07a81); + tve_writel(TV_ADJ_TIMING, 0x96B40000); + tve_writel(TV_ACT_ST, 0x001500D6); + tve_writel(TV_ACT_TIMING, 0x169800FC); + + } else if (mode == TVOUT_CVBS_PAL) { + tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(1) | + v_Y_AGC_PULSE_ON(1) | v_Y_VIDEO_ON(1) | + v_Y_SYNC_ON(1) | v_CVBS_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, 0x002e553c); + tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00007579); + + tve_writel(TV_FREQ_SC, 0x2A098ACB); + tve_writel(TV_SYNC_TIMING, 0x00C28381); + tve_writel(TV_ADJ_TIMING, 0xB6C00880); + tve_writel(TV_ACT_ST, 0x001500F6); + tve_writel(TV_ACT_TIMING, 0x2694011D); + } +} + +static int tve_switch_fb(const struct fb_videomode *modedb, int enable) +{ + struct rk_screen *screen; + + if(modedb == NULL) + return -1; + screen = kzalloc(sizeof(struct rk_screen), GFP_KERNEL); + if(screen == NULL) + return -1; + + memset(screen, 0, sizeof(struct rk_screen)); + /* screen type & face */ + screen->type = SCREEN_TVOUT; + screen->face = OUT_P888; + + screen->mode = *modedb; + + /* Pin polarity */ + if(FB_SYNC_HOR_HIGH_ACT & modedb->sync) + screen->pin_hsync = 1; + else + screen->pin_hsync = 0; + if(FB_SYNC_VERT_HIGH_ACT & modedb->sync) + screen->pin_vsync = 1; + else + screen->pin_vsync = 0; + + screen->pin_den = 0; + screen->pin_dclk = 1; + screen->pixelrepeat = 1; + + /* Swap rule */ + screen->swap_rb = 0; + screen->swap_rg = 0; + screen->swap_gb = 0; + screen->swap_delta = 0; + screen->swap_dumy = 0; + + /* Operation function*/ + screen->init = NULL; + screen->standby = NULL; + + rk_fb_switch_screen(screen, enable, 0); + + kfree(screen); + if(enable) { + if(screen->mode.yres == 480) + tve_set_mode(TVOUT_CVBS_NTSC); + else + tve_set_mode(TVOUT_CVBS_PAL); + } + return 0; +} + +static int cvbs_set_enable(struct rk_display_device *device, int enable) +{ + if(rk3036_tve->enable != enable) + { + rk3036_tve->enable = enable; + if(rk3036_tve->suspend) + return 0; + + if(enable == 0) { + dac_enable(false); + tve_switch_fb(rk3036_tve->mode, 0); + } + else if(enable == 1) { + tve_switch_fb(rk3036_tve->mode, 1); + dac_enable(true); + } + } + return 0; +} + +static int cvbs_get_enable(struct rk_display_device *device) +{ + return rk3036_tve->enable; +} + +static int cvbs_get_status(struct rk_display_device *device) +{ + return 1; +} + +static int cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist) +{ + *modelist = &(rk3036_tve->modelist); + return 0; +} + +static int cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(rk3036_cvbs_mode); i++) + { + if(fb_mode_is_equal(&rk3036_cvbs_mode[i], mode)) + { + if( rk3036_tve->mode != &rk3036_cvbs_mode[i] ) { + rk3036_tve->mode = (struct fb_videomode *)&rk3036_cvbs_mode[i]; + if(rk3036_tve->enable && !rk3036_tve->suspend) + dac_enable(false); + tve_switch_fb(rk3036_tve->mode, 1); + dac_enable(true); + } + return 0; + } + } + + return -1; +} + +static int cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode) +{ + *mode = *(rk3036_tve->mode); + return 0; +} + +static struct rk_display_ops cvbs_display_ops = { + .setenable = cvbs_set_enable, + .getenable = cvbs_get_enable, + .getstatus = cvbs_get_status, + .getmodelist = cvbs_get_modelist, + .setmode = cvbs_set_mode, + .getmode = cvbs_get_mode, +}; + +static int display_cvbs_probe(struct rk_display_device *device, void *devdata) +{ + device->owner = THIS_MODULE; + strcpy(device->type, "TV"); + device->name = "cvbs"; + device->priority = DISPLAY_PRIORITY_TV; + device->priv_data = devdata; + device->ops = &cvbs_display_ops; + return 1; +} + +static struct rk_display_driver display_cvbs = { + .probe = display_cvbs_probe, +}; + +static int rk3036_tve_probe(struct platform_device *pdev) +{ + struct resource *res; + int i; + + rk3036_tve = devm_kzalloc(&pdev->dev, sizeof(struct rk3036_tve), + GFP_KERNEL); + if(!rk3036_tve) { + dev_err(&pdev->dev, "rk3036 tv encoder device kmalloc fail!"); + return -ENOMEM; + } + platform_set_drvdata(pdev, rk3036_tve); + rk3036_tve->dev = &pdev->dev; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rk3036_tve->reg_phy_base = res->start; + rk3036_tve->len = resource_size(res); + rk3036_tve->regbase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(rk3036_tve->regbase)) { + dev_err(&pdev->dev, "rk3036 tv encoder device map registers failed!"); + return PTR_ERR(rk3036_tve->regbase); + } + + INIT_LIST_HEAD(&(rk3036_tve->modelist)); + for(i = 0; i < ARRAY_SIZE(rk3036_cvbs_mode); i++) + fb_add_videomode(&rk3036_cvbs_mode[i], &(rk3036_tve->modelist)); + + rk3036_tve->ddev = rk_display_device_register(&display_cvbs, &pdev->dev, NULL); + rk_display_device_enable(rk3036_tve->ddev); + + dev_info(&pdev->dev, "rk3036 tv encoder probe ok\n"); + return 0; +} + +static void rk3036_tve_shutdown(struct platform_device *pdev) +{ + +} + +#if defined(CONFIG_OF) +static const struct of_device_id rk3036_tve_dt_ids[] = { + {.compatible = "rockchip,rk3036-tve",}, + {} +}; +#endif + +static struct platform_driver rk3036_tve_driver = { + .probe = rk3036_tve_probe, + .remove = NULL, + .driver = { + .name = "rk3036-tve", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rk3036_tve_dt_ids), + }, + .shutdown = rk3036_tve_shutdown, +}; + +static int __init rk3036_tve_init(void) +{ + return platform_driver_register(&rk3036_tve_driver); +} + +static void __exit rk3036_tve_exit(void) +{ + platform_driver_unregister(&rk3036_tve_driver); +} + +module_init(rk3036_tve_init); +module_exit(rk3036_tve_exit); + +/* Module information */ +MODULE_DESCRIPTION("ROCKCHIP RK3036 TV Encoder "); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/drivers/video/rockchip/tve/rk3036/rk3036_tve.h b/drivers/video/rockchip/tve/rk3036/rk3036_tve.h new file mode 100644 index 000000000000..d36573e0f5b0 --- /dev/null +++ b/drivers/video/rockchip/tve/rk3036/rk3036_tve.h @@ -0,0 +1,100 @@ +#ifndef __RK3036_TVE_H__ +#define __RK3036_TVE_H__ + +#define TV_CTRL (0x00) + #define m_CVBS_MODE (1 << 24) + #define m_CLK_UPSTREAM_EN (3 << 18) + #define m_TIMING_EN (3 << 16) + #define m_LUMA_FILTER_GAIN (3 << 9) + #define m_LUMA_FILTER_BW (1 << 8) + #define m_CSC_PATH (3 << 1) + + #define v_CVBS_MODE(x) ( (x & 1) << 24) + #define v_CLK_UPSTREAM_EN(x) ( (x & 3) << 18) + #define v_TIMING_EN(x) ( (x & 3) << 16) + #define v_LUMA_FILTER_GAIN(x) ( (x & 3) << 9) + #define v_LUMA_FILTER_UPSAMPLE(x) ( (x & 1) << 8) + #define v_CSC_PATH(x) ( (x & 3) << 1) + +#define TV_SYNC_TIMING (0x04) +#define TV_ACT_TIMING (0x08) +#define TV_ADJ_TIMING (0x0c) +#define TV_FREQ_SC (0x10) +#define TV_LUMA_FILTER0 (0x14) +#define TV_LUMA_FILTER1 (0x18) +#define TV_LUMA_FILTER2 (0x1C) +#define TV_ACT_ST (0x34) +#define TV_ROUTING (0x38) + #define m_DAC_SENSE_EN (1 << 27) + #define m_Y_IRE_7_5 (1 << 19) + #define m_Y_AGC_PULSE_ON (1 << 15) + #define m_Y_VIDEO_ON (1 << 11) + #define m_Y_SYNC_ON (1 << 7) + #define m_MONO_EN (1 << 2) + #define m_PIC_MODE (1 << 1) + + #define v_DAC_SENSE_EN(x) ( (x & 1) << 27) + #define v_Y_IRE_7_5(x) ( (x & 1) << 19) + #define v_Y_AGC_PULSE_ON(x) ( (x & 1) << 15) + #define v_Y_VIDEO_ON(x) ( (x & 1) << 11) + #define v_Y_SYNC_ON(x) ( (x & 1) << 7) + #define v_MONO_EN(x) ( (x & 1) << 2) + #define v_PIC_MODE(x) ( (x & 1) << 1) + +#define TV_SYNC_ADJUST (0x50) +#define TV_STATUS (0x54) +#define TV_RESET (0x68) + #define m_RESET (1 << 1); + #define v_RESET(x) ( (x & 1) << 1) +#define TV_SATURATION (0x78) +#define TV_BW_CTRL (0x8C) + #define m_CHROMA_BW (3 << 4) + #define m_COLOR_DIFF_BW (0xf) + + enum { + BP_FILTER_PASS = 0, + BP_FILTER_NTSC, + BP_FILTER_PAL, + }; + enum { + COLOR_DIFF_FILTER_OFF = 0, + COLOR_DIFF_FILTER_BW_0_6, + COLOR_DIFF_FILTER_BW_1_3, + COLOR_DIFF_FILTER_BW_2_0 + }; + + #define v_CHROMA_BW(x) ((3 & x) << 4) + #define v_COLOR_DIFF_BW(x) (0xF & x) + +#define TV_BRIGHTNESS_CONTRAST (0x90) + +#define m_EXTREF_EN (1 << 0) +#define m_VBG_EN (1 << 1) +#define m_DAC_EN (1 << 2) +#define m_SENSE_EN (1 << 3) +#define m_BIAS_EN (7 << 4) +#define m_DAC_GAIN (0x3f << 7) + +enum { + TVOUT_CVBS_NTSC = 0, + TVOUT_CVBS_PAL, +}; + +#define TVOUT_DEAULT TVOUT_CVBS_PAL + +#define grf_writel(offset, v) do{ writel_relaxed(v, RK_GRF_VIRT + offset);dsb();} while (0) + +struct rk3036_tve { + struct device *dev; + void __iomem *regbase; + u32 reg_phy_base; /* physical basic address of register*/ + u32 len; /* physical map length of register*/ + + struct rk_display_device *ddev; + unsigned int enable; + unsigned int suspend; + struct fb_videomode *mode; + struct list_head modelist; +}; + +#endif \ No newline at end of file diff --git a/drivers/video/rockchip/tve/rk610/Kconfig b/drivers/video/rockchip/tve/rk610/Kconfig new file mode 100644 index 000000000000..74eaf28651be --- /dev/null +++ b/drivers/video/rockchip/tve/rk610/Kconfig @@ -0,0 +1,14 @@ +config RK610_TVOUT + bool "RK610(Jetta) tvout support" + depends on MFD_RK610 + default n + help + Support Jetta(RK610) to output YPbPr and CVBS. + +config RK610_TVOUT_YPbPr + bool "support YPbPr output" + depends on RK610_TVOUT + +config RK610_TVOUT_CVBS + bool "support CVBS output" + depends on RK610_TVOUT diff --git a/drivers/video/rockchip/tve/rk610/Makefile b/drivers/video/rockchip/tve/rk610/Makefile new file mode 100644 index 000000000000..b7d457326d26 --- /dev/null +++ b/drivers/video/rockchip/tve/rk610/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the jetta tv control. +# +obj-$(CONFIG_RK610_TVOUT) += rk610_tv.o +obj-$(CONFIG_RK610_TVOUT_YPbPr) += rk610_tv_ypbpr.o +obj-$(CONFIG_RK610_TVOUT_CVBS) += rk610_tv_cvbs.o \ No newline at end of file diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv.c b/drivers/video/rockchip/tve/rk610/rk610_tv.c new file mode 100644 index 000000000000..83a6cec97665 --- /dev/null +++ b/drivers/video/rockchip/tve/rk610/rk610_tv.c @@ -0,0 +1,246 @@ +/* + * rk610_tv.c + * + * Driver for rockchip rk610 tv control + * Copyright (C) 2009 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rk610_tv.h" +#include "../../rk29_fb.h" + +#define DRV_NAME "rk610_tvout" +#define RK610_I2C_RATE 100*1000 + +volatile int rk610_tv_output_status = RK610_TVOUT_DEAULT; +static struct i2c_client *rk610_tv_i2c_client = NULL; + +int rk610_tv_wirte_reg(u8 reg, u8 data) +{ + int ret; + if(rk610_tv_i2c_client == NULL) + return -1; + ret = i2c_master_reg8_send(rk610_tv_i2c_client, reg, &data, 1, RK610_I2C_RATE); + if (ret > 0) + ret = 0; + return ret; +} + +int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode) +{ + struct rk_screen *screen; + + if(modedb == NULL) + return -1; + screen = kzalloc(sizeof(struct rk_screen), GFP_KERNEL); + if(screen == NULL) + return -1; + + memset(screen, 0, sizeof(struct rk_screen)); + /* screen type & face */ + screen->type = SCREEN_HDMI; + screen->mode = modedb->vmode; + screen->face = modedb->flag; + /* Screen size */ + screen->x_res = modedb->xres; + screen->y_res = modedb->yres; + + /* Timing */ + screen->pixclock = modedb->pixclock; + + screen->lcdc_aclk = 500000000; + screen->left_margin = modedb->left_margin; + screen->right_margin = modedb->right_margin; + screen->hsync_len = modedb->hsync_len; + screen->upper_margin = modedb->upper_margin; + screen->lower_margin = modedb->lower_margin; + screen->vsync_len = modedb->vsync_len; + + /* Pin polarity */ + if(FB_SYNC_HOR_HIGH_ACT & modedb->sync) + screen->pin_hsync = 1; + else + screen->pin_hsync = 0; + if(FB_SYNC_VERT_HIGH_ACT & modedb->sync) + screen->pin_vsync = 1; + else + screen->pin_vsync = 0; + screen->pin_den = 0; + screen->pin_dclk = 0; + + /* Swap rule */ + screen->swap_rb = 0; + screen->swap_rg = 0; + screen->swap_gb = 0; + screen->swap_delta = 0; + screen->swap_dumy = 0; + + /* Operation function*/ + screen->init = NULL; + screen->standby = NULL; + + switch(tv_mode) + { +#ifdef CONFIG_RK610_TVOUT_CVBS + case TVOUT_CVBS_NTSC: + case TVOUT_CVBS_PAL: + screen->init = rk610_tv_cvbs_init;; + break; +#endif + +#ifdef CONFIG_RK610_TVOUT_YPbPr + case TVOUT_YPbPr_720x480p_60: + case TVOUT_YPbPr_720x576p_50: + case TVOUT_YPbPr_1280x720p_50: + case TVOUT_YPbPr_1280x720p_60: + //case TVOUT_YPbPr_1920x1080i_50: + case TVOUT_YPbPr_1920x1080i_60: + case TVOUT_YPbPr_1920x1080p_50: + case TVOUT_YPbPr_1920x1080p_60: + screen->init = rk610_tv_ypbpr_init; + break; +#endif + default:{ + kfree(screen); + return -1; + } + break; + } + rk610_tv_output_status = tv_mode; + FB_Switch_Screen(screen, 1); + kfree(screen); + return 0; +} + +int rk610_tv_standby(int type) +{ + int ret; + + switch(type) + { + #ifdef CONFIG_RK610_TVOUT_CVBS + case RK610_TVOUT_CVBS: + if(rk610_cvbs_monspecs.enable == 0) + return 0; + #ifdef CONFIG_RK610_TVOUT_YPbPr + if(rk610_ypbpr_monspecs.enable == 1) + return 0; + #endif + break; + #endif + #ifdef CONFIG_RK610_TVOUT_YPbPr + case RK610_TVOUT_YPBPR: + if(rk610_ypbpr_monspecs.enable == 0) + return 0; + #ifdef CONFIG_RK610_TVOUT_CVBS + if(rk610_cvbs_monspecs.enable == 1) + return 0; + #endif + break; + #endif + default: + break; + } + + ret = rk610_tv_wirte_reg(TVE_POWERCR, 0); + if(ret < 0){ + printk("[%s] rk610_tv_wirte_reg err!\n", __FUNCTION__); + return ret; + } + + ret = rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, 0); + if(ret < 0){ + printk("[%s] rk610_control_send_byte err!\n", __FUNCTION__); + return ret; + } + return 0; +} + +static int rk610_tv_probe(struct i2c_client *client,const struct i2c_device_id *id) +{ + int rc = 0; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + rc = -ENODEV; + goto failout; + } + rk610_tv_i2c_client = client; + +#ifdef CONFIG_RK610_TVOUT_YPbPr + rk610_register_display_ypbpr(&client->dev); + if(rk610_tv_output_status > TVOUT_CVBS_PAL) + rk_display_device_enable(rk610_ypbpr_monspecs.ddev); +#endif + +#ifdef CONFIG_RK610_TVOUT_CVBS + rk610_register_display_cvbs(&client->dev); + if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) + rk_display_device_enable(rk610_cvbs_monspecs.ddev); +#endif + + printk(KERN_INFO "rk610_tv ver 1.0 probe ok\n"); + return 0; +failout: + kfree(client); + return rc; +} + +static int rk610_tv_remove(struct i2c_client *client) +{ + return 0; +} + + +static const struct i2c_device_id rk610_tv_id[] = { + { DRV_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rk610_tv_id); + +static struct i2c_driver rk610_tv_driver = { + .driver = { + .name = DRV_NAME, + }, + .id_table = rk610_tv_id, + .probe = rk610_tv_probe, + .remove = rk610_tv_remove, +}; + +static int __init rk610_tv_init(void) +{ + int ret = 0; + ret = i2c_add_driver(&rk610_tv_driver); + if(ret < 0){ + printk("i2c_add_driver err, ret = %d\n", ret); + } + return ret; +} + +static void __exit rk610_tv_exit(void) +{ + i2c_del_driver(&rk610_tv_driver); +} + +module_init(rk610_tv_init); +//late_initcall(rk610_tv_init); +module_exit(rk610_tv_exit); + +/* Module information */ +MODULE_DESCRIPTION("ROCKCHIP RK610 TV Output"); +MODULE_LICENSE("GPL"); + + diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv.h b/drivers/video/rockchip/tve/rk610/rk610_tv.h new file mode 100644 index 000000000000..ead23a8a06a1 --- /dev/null +++ b/drivers/video/rockchip/tve/rk610/rk610_tv.h @@ -0,0 +1,131 @@ +#ifndef _RK610_TV_H +#define _RK610_TV_H +#include +#include +#include +#include +#ifdef CONFIG_ARCH_RK29 +#include +#endif +#include "../screen/screen.h" +#include "../../rk29_fb.h" +#include + +#define TVE_VFCR 0x00 + #define TVE_VFCR_ENABLE_SUBCARRIER_RESET 0 << 6 + #define TVE_VFCR_DISABLE_SUBCARRIER_RESET 1 << 6 + #define TVE_VFCR_VIN_RANGE_16_235 0 << 3 + #define TVE_VFCR_VIN_RANGE_1_254 1 << 3 + #define TVE_VFCR_BLACK_7_5_IRE 0 << 2 + #define TVE_VFCR_BLACK_0_IRE 1 << 2 + #define TVE_VFCR_NTSC 0 + #define TVE_VFCR_PAL_M 1 + #define TVE_VFCR_PAL_B_N 2 + #define TVE_VFCR_PAL_NC 3 + +#define TVE_VINCR 0x01 + #define TVE_VINCR_PIX_DATA_DELAY(n) (n << 5) + #define TVE_VINCR_H_SYNC_POLARITY_NEGTIVE 0 << 4 + #define TVE_VINCR_H_SYNC_POLARITY_POSITIVE 1 << 4 + #define TVE_VINCR_V_SYNC_POLARITY_NEGTIVE 0 << 3 + #define TVE_VINCR_V_SYNC_POLARITY_POSITIVE 1 << 3 +enum { + INPUT_FORMAT_BT601_SLAVE = 0, + INPUT_FORMAT_BT656, + INPUT_FORMAT_BT601_MASTER, + INPUT_FORMAT_INTERNAL_COLLOR_BAR +}; + #define TVE_VINCR_INPUT_FORMAT(n) (n << 1) + #define TVE_VINCR_VSYNC_FUNCTION_VSYNC 0 + #define TVE_VINCR_VSYNC_FUNCTION_FIELD 1 + +#define TVE_VOUTCR 0x02 + #define TVE_VOUTCR_OUTPUT_CVBS 0 << 6 + #define TVE_VOUTCR_OUTPUT_YPBPR 1 << 6 + #define TVE_VOUTCR_OUTPUT_ENABLE_BLUE 1 << 5 + #define TVE_VOUTCR_OUTPUT_ENABLE_BLACK 1 << 4 + #define TVE_VOUTCR_DISABLE_CVBS_COLOR 1 << 3 + #define TVE_VOUTCR_CVBS_Y2C_DELAY(n) (n << 0) + +#define TVE_POWERCR 0x03 + #define TVE_PIX_CLK_INVERSE_ENABLE 1 << 4 + #define TVE_DAC_CLK_INVERSE_DISABLE 1 << 3 + #define TVE_DAC_Y_ENABLE 1 << 2 + #define TVE_DAC_U_ENABLE 1 << 1 + #define TVE_DAC_V_ENABLE 1 << 0 + +#define TVE_HDTVCR 0x05 + #define TVE_RESET 1 << 7 + #define TVE_FILTER(n) (n << 5) + #define TVE_COLOR_CONVERT_REC601 0 << 4 + #define TVE_COLOR_CONVERT_REC709 1 << 4 + #define TVE_INPUT_DATA_RGB 0 << 3 + #define TVE_INPUT_DATA_YUV 1 << 3 + #define TVE_OUTPUT_50HZ 0 << 2 + #define TVE_OUTPUT_60HZ 1 << 2 + #define TVE_OUTPUT_MODE_PAL_NTSC 0 + #define TVE_OUTPUT_MODE_576P 1 + #define TVE_OUTPUT_MODE_480P 2 + #define TVE_OUTPUT_MODE_720P 3 + +#define TVE_YADJCR 0x06 + #define TVE_OUTPUT_MODE_1080P 1 << 6 + #define TVE_OUTPUT_MODE_1080I 1 << 5 + #define TVE_Y_ADJ_VALUE(n) n +#define TVE_YCBADJCR 0x07 +#define TVE_YCRADJCR 0x08 + +/******************* TVOUT OUTPUT TYPE **********************/ +struct rk610_monspecs { + struct rk_display_device *ddev; + unsigned int enable; + struct fb_videomode *mode; + struct list_head modelist; + unsigned int mode_set; +}; + +enum { + TVOUT_CVBS_NTSC = 1, + TVOUT_CVBS_PAL, + TVOUT_YPbPr_720x480p_60, + TVOUT_YPbPr_720x576p_50, + TVOUT_YPbPr_1280x720p_50, + TVOUT_YPbPr_1280x720p_60, + //TVOUT_YPbPr_1920x1080i_50, + TVOUT_YPbPr_1920x1080i_60, + TVOUT_YPbPr_1920x1080p_50, + TVOUT_YPbPr_1920x1080p_60 +}; + +#define RK610_TVOUT_DEAULT TVOUT_CVBS_NTSC + +enum { + RK610_TVOUT_CVBS = 0, + RK610_TVOUT_YC, + RK610_TVOUT_YPBPR, +}; + +extern volatile int rk610_tv_output_status; +extern struct rk_display_ops rk610_display_ops; + +extern int FB_Switch_Screen( struct rk_screen *screen, u32 enable ); + +extern int rk610_tv_wirte_reg(u8 reg, u8 data); +extern int rk610_tv_standby(int type); +extern int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode); +extern int rk610_register_display(struct device *parent); + +#ifdef CONFIG_RK610_TVOUT_YPbPr +extern int rk610_tv_ypbpr_init(void); +extern int rk610_register_display_ypbpr(struct device *parent); +extern struct rk610_monspecs rk610_ypbpr_monspecs; +#endif + +#ifdef CONFIG_RK610_TVOUT_CVBS +extern int rk610_tv_cvbs_init(void); +extern int rk610_register_display_cvbs(struct device *parent); +extern struct rk610_monspecs rk610_cvbs_monspecs; +#endif + +#endif + diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c b/drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c new file mode 100644 index 000000000000..ea0fe8a0d79c --- /dev/null +++ b/drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c @@ -0,0 +1,209 @@ +#include +#include +#include +#include "rk610_tv.h" + + +#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL +#define RK610_LED_CVBS_PIN RK29_PIN4_PD3 +#else +#define RK610_LED_CVBS_PIN INVALID_GPIO +#endif + +#ifdef USE_RGB2CCIR +static const struct fb_videomode rk610_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, 116, 16, 25, 14, 6, 6, 0, 1, OUT_P888 }, + { "PAL", 50, 720, 576, 27000000, 126, 12, 37, 6, 6, 6, 0, 1, OUT_P888 }, +}; +#else +static const struct fb_videomode rk610_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, 116, 16, 16, 3, 6, 3, 0, 1, OUT_CCIR656 }, + { "PAL", 50, 720, 576, 27000000, 126, 12, 19, 2, 6, 3, 0, 1, OUT_CCIR656 }, +}; +#endif + +struct rk610_monspecs rk610_cvbs_monspecs; + + +int rk610_tv_cvbs_init(void) +{ + unsigned char TVE_Regs[9]; + unsigned char TVE_CON_Reg; + int ret, i; + + rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET); + + memset(TVE_Regs, 0, 9); + TVE_CON_Reg = TVE_CONTROL_CVBS_3_CHANNEL_ENALBE; + TVE_Regs[TVE_VINCR] = TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC; + TVE_Regs[TVE_POWERCR] = TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE; + TVE_Regs[TVE_VOUTCR] = TVE_VOUTCR_OUTPUT_CVBS; + TVE_Regs[TVE_YADJCR] = 0x17; + TVE_Regs[TVE_YCBADJCR] = 0x10; + TVE_Regs[TVE_YCRADJCR] = 0x10; + + switch(rk610_tv_output_status) { + case TVOUT_CVBS_NTSC: + TVE_Regs[TVE_VFCR] = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_7_5_IRE | TVE_VFCR_NTSC; + #ifdef USE_RGB2CCIR + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC; + TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_NTSC | RGB2CCIR_ENABLE; + #else + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC; + #endif + break; + case TVOUT_CVBS_PAL: + TVE_Regs[TVE_VFCR] = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_B_N; + #ifdef USE_RGB2CCIR + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC; + TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_PAL | RGB2CCIR_ENABLE; + #else + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC; + #endif + break; + default: + return -1; + } + + for(i = 0; i < sizeof(TVE_Regs); i++){ +// printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]); + ret = rk610_tv_wirte_reg(i, TVE_Regs[i]); + if(ret < 0){ + printk(KERN_ERR "rk610_tv_wirte_reg %d err!\n", i); + return ret; + } + } +// printk(KERN_ERR "TVE_CON_Reg = 0x%02x\n", TVE_CON_Reg); + rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg); + #ifdef USE_RGB2CCIR + rk610_control_send_byte(RK610_CONTROL_REG_CCIR_RESET, 0x01); + #endif + return 0; +} + +static int rk610_cvbs_set_enable(struct rk_display_device *device, int enable) +{ + if(rk610_cvbs_monspecs.enable != enable || rk610_cvbs_monspecs.mode_set != rk610_tv_output_status) + { + if(enable == 0) + { + rk610_tv_standby(RK610_TVOUT_CVBS); + rk610_cvbs_monspecs.enable = 0; + if(RK610_LED_CVBS_PIN != INVALID_GPIO) + gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH); + } + else if(enable == 1) + { + rk610_switch_fb(rk610_cvbs_monspecs.mode, rk610_cvbs_monspecs.mode_set); + rk610_cvbs_monspecs.enable = 1; + if(RK610_LED_CVBS_PIN != INVALID_GPIO) + gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_LOW); + } + } + return 0; +} + +static int rk610_cvbs_get_enable(struct rk_display_device *device) +{ + return rk610_cvbs_monspecs.enable; +} + +static int rk610_cvbs_get_status(struct rk_display_device *device) +{ + if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) + return 1; + else + return 0; +} + +static int rk610_cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist) +{ + *modelist = &(rk610_cvbs_monspecs.modelist); + return 0; +} + +static int rk610_cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++) + { + if(fb_mode_is_equal(&rk610_cvbs_mode[i], mode)) + { + if( ((i + 1) != rk610_tv_output_status) ) + { + rk610_cvbs_monspecs.mode_set = i + 1; + rk610_cvbs_monspecs.mode = (struct fb_videomode *)&rk610_cvbs_mode[i]; + } + return 0; + } + } + + return -1; +} + +static int rk610_cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode) +{ + *mode = *(rk610_cvbs_monspecs.mode); + return 0; +} + +static struct rk_display_ops rk610_cvbs_display_ops = { + .setenable = rk610_cvbs_set_enable, + .getenable = rk610_cvbs_get_enable, + .getstatus = rk610_cvbs_get_status, + .getmodelist = rk610_cvbs_get_modelist, + .setmode = rk610_cvbs_set_mode, + .getmode = rk610_cvbs_get_mode, +}; + +static int rk610_display_cvbs_probe(struct rk_display_device *device, void *devdata) +{ + device->owner = THIS_MODULE; + strcpy(device->type, "TV"); + device->priority = DISPLAY_PRIORITY_TV; + device->priv_data = devdata; + device->ops = &rk610_cvbs_display_ops; + return 1; +} + +static struct rk_display_driver display_rk610_cvbs = { + .probe = rk610_display_cvbs_probe, +}; + +int rk610_register_display_cvbs(struct device *parent) +{ + int i; + + memset(&rk610_cvbs_monspecs, 0, sizeof(struct rk610_monspecs)); + INIT_LIST_HEAD(&rk610_cvbs_monspecs.modelist); + for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++) + fb_add_videomode(&rk610_cvbs_mode[i], &rk610_cvbs_monspecs.modelist); + if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) { + rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[rk610_tv_output_status - 1]); + rk610_cvbs_monspecs.mode_set = rk610_tv_output_status; + } + else { + rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[0]); + rk610_cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC; + } + rk610_cvbs_monspecs.ddev = rk_display_device_register(&display_rk610_cvbs, parent, NULL); + if(RK610_LED_CVBS_PIN != INVALID_GPIO) + { + if(gpio_request(RK610_LED_CVBS_PIN, NULL) != 0) + { + gpio_free(RK610_LED_CVBS_PIN); + dev_err(rk610_cvbs_monspecs.ddev->dev, ">>>>>> RK610_LED_CVBS_PIN gpio_request err \n "); + return -1; + } + gpio_pull_updown(RK610_LED_CVBS_PIN,GPIOPullUp); + gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH); + } + return 0; +} diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c b/drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c new file mode 100644 index 000000000000..af74126f7604 --- /dev/null +++ b/drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c @@ -0,0 +1,229 @@ +#include +#include +#include +#include "rk610_tv.h" + + +#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL +#define RK610_LED_YPbPr_PIN RK29_PIN4_PD5 +#else +#define RK610_LED_YPbPr_PIN INVALID_GPIO +#endif +#define E(fmt, arg...) printk("<3>!!!%s:%d: " fmt, __FILE__, __LINE__, ##arg) + +static const struct fb_videomode rk610_YPbPr_mode [] = { + //name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag + { "YPbPr480p", 60, 720, 480, 27000000, 55, 19, 37, 5, 64, 5, 0, 0, OUT_P888 }, + { "YPbPr576p", 50, 720, 576, 27000000, 68, 12, 39, 5, 64, 5, 0, 0, OUT_P888 }, + { "YPbPr720p@50", 50, 1280, 720, 74250000, 600, 0, 20, 5, 100, 5, 0, 0, OUT_P888 }, + { "YPbPr720p@60", 60, 1280, 720, 74250000, 270, 0, 20, 5, 100, 5, 0, 0, OUT_P888 }, + //{ "YPbPr1080i@50", 50, 1920, 1080, 148500000, 620, 0, 15, 2, 100, 5, 0, 1, OUT_CCIR656 }, + { "YPbPr1080i@60", 60, 1920, 1080, 148500000, 180, 0, 15, 2, 100, 5, 0, 1, OUT_CCIR656 }, + { "YPbPr1080p@50", 50, 1920, 1080, 148500000, 620, 0, 36, 4, 100, 5, 0, 0, OUT_P888 }, + { "YPbPr1080p@60", 60, 1920, 1080, 148500000, 180, 0, 36, 4, 100, 5, 0, 0, OUT_P888 }, +}; + +struct rk610_monspecs rk610_ypbpr_monspecs; + +int rk610_tv_ypbpr_init(void) +{ + unsigned char TVE_Regs[9]; + unsigned char TVE_CON_Reg; + int i, ret; + + rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET); + memset(TVE_Regs, 0, 9); + + TVE_CON_Reg = 0x00; + + TVE_Regs[TVE_VINCR] = TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC; + TVE_Regs[TVE_POWERCR] = TVE_DAC_CLK_INVERSE_DISABLE | TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE; + TVE_Regs[TVE_VOUTCR] = TVE_VOUTCR_OUTPUT_YPBPR; + TVE_Regs[TVE_YADJCR] = 0x17; + TVE_Regs[TVE_YCBADJCR] = 0x10; + TVE_Regs[TVE_YCRADJCR] = 0x10; + + switch(rk610_tv_output_status) + { + case TVOUT_YPbPr_720x480p_60: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_480P; + break; + case TVOUT_YPbPr_720x576p_50: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_576P; + break; + case TVOUT_YPbPr_1280x720p_50: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_720P; + break; + case TVOUT_YPbPr_1280x720p_60: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_720P; + break; + /*case TVOUT_YPbPr_1920x1080i_50: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_50HZ; + TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080I; + break; + */ + case TVOUT_YPbPr_1920x1080i_60: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_60HZ; + TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080I; + break; + case TVOUT_YPbPr_1920x1080p_50: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ; + TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080P; + break; + case TVOUT_YPbPr_1920x1080p_60: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ; + TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080P; + break; + default: + return -1; + } + + rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg); + + for(i = 0; i < sizeof(TVE_Regs); i++){ +// printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]); + ret = rk610_tv_wirte_reg(i, TVE_Regs[i]); + if(ret < 0){ + E("rk610_tv_wirte_reg %d err!\n", i); + return ret; + } + } + return 0; +} + +static int rk610_ypbpr_set_enable(struct rk_display_device *device, int enable) +{ + if(rk610_ypbpr_monspecs.enable != enable || rk610_ypbpr_monspecs.mode_set != rk610_tv_output_status) + { + if(enable == 0) + { + rk610_tv_standby(RK610_TVOUT_YPBPR); + rk610_ypbpr_monspecs.enable = 0; + if(RK610_LED_YPbPr_PIN != INVALID_GPIO) + gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH); + } + else if(enable == 1) + { + rk610_switch_fb(rk610_ypbpr_monspecs.mode, rk610_ypbpr_monspecs.mode_set); + rk610_ypbpr_monspecs.enable = 1; + if(RK610_LED_YPbPr_PIN != INVALID_GPIO) + gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_LOW); + } + } + return 0; +} + +static int rk610_ypbpr_get_enable(struct rk_display_device *device) +{ + return rk610_ypbpr_monspecs.enable; +} + +static int rk610_ypbpr_get_status(struct rk_display_device *device) +{ + if(rk610_tv_output_status > TVOUT_CVBS_PAL) + return 1; + else + return 0; +} + +static int rk610_ypbpr_get_modelist(struct rk_display_device *device, struct list_head **modelist) +{ + *modelist = &(rk610_ypbpr_monspecs.modelist); + return 0; +} + +static int rk610_ypbpr_set_mode(struct rk_display_device *device, struct fb_videomode *mode) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++) + { + if(fb_mode_is_equal(&rk610_YPbPr_mode[i], mode)) + { + if( (i + 3) != rk610_tv_output_status ) + { + rk610_ypbpr_monspecs.mode_set = i + 3; + rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&rk610_YPbPr_mode[i]; + } + return 0; + } + } + + return -1; +} + +static int rk610_ypbpr_get_mode(struct rk_display_device *device, struct fb_videomode *mode) +{ + *mode = *(rk610_ypbpr_monspecs.mode); + return 0; +} + +static struct rk_display_ops rk610_ypbpr_display_ops = { + .setenable = rk610_ypbpr_set_enable, + .getenable = rk610_ypbpr_get_enable, + .getstatus = rk610_ypbpr_get_status, + .getmodelist = rk610_ypbpr_get_modelist, + .setmode = rk610_ypbpr_set_mode, + .getmode = rk610_ypbpr_get_mode, +}; + +static int rk610_display_YPbPr_probe(struct rk_display_device *device, void *devdata) +{ + device->owner = THIS_MODULE; + strcpy(device->type, "YPbPr"); + device->priority = DISPLAY_PRIORITY_YPbPr; + device->priv_data = devdata; + device->ops = &rk610_ypbpr_display_ops; + return 1; +} + +static struct rk_display_driver display_rk610_YPbPr = { + .probe = rk610_display_YPbPr_probe, +}; + +int rk610_register_display_ypbpr(struct device *parent) +{ + int i; + + memset(&rk610_ypbpr_monspecs, 0, sizeof(struct rk610_monspecs)); + INIT_LIST_HEAD(&rk610_ypbpr_monspecs.modelist); + for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++) + fb_add_videomode(&rk610_YPbPr_mode[i], &rk610_ypbpr_monspecs.modelist); + if(rk610_tv_output_status > TVOUT_CVBS_PAL) { + rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[rk610_tv_output_status - 3]); + rk610_ypbpr_monspecs.mode_set = rk610_tv_output_status; + } + else { + rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[3]); + rk610_ypbpr_monspecs.mode_set = TVOUT_YPbPr_1280x720p_60; + } + rk610_ypbpr_monspecs.ddev = rk_display_device_register(&display_rk610_YPbPr, parent, NULL); + if(RK610_LED_YPbPr_PIN != INVALID_GPIO) + { + if(gpio_request(RK610_LED_YPbPr_PIN, NULL) != 0) + { + gpio_free(RK610_LED_YPbPr_PIN); + dev_err(rk610_ypbpr_monspecs.ddev->dev, ">>>>>> RK610_LED_YPbPr_PIN gpio_request err \n "); + return -1; + } + gpio_pull_updown(RK610_LED_YPbPr_PIN,GPIOPullUp); + gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH); + } + return 0; +} diff --git a/drivers/video/rockchip/tve/rk610_tv.c b/drivers/video/rockchip/tve/rk610_tv.c deleted file mode 100644 index 83a6cec97665..000000000000 --- a/drivers/video/rockchip/tve/rk610_tv.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * rk610_tv.c - * - * Driver for rockchip rk610 tv control - * Copyright (C) 2009 - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rk610_tv.h" -#include "../../rk29_fb.h" - -#define DRV_NAME "rk610_tvout" -#define RK610_I2C_RATE 100*1000 - -volatile int rk610_tv_output_status = RK610_TVOUT_DEAULT; -static struct i2c_client *rk610_tv_i2c_client = NULL; - -int rk610_tv_wirte_reg(u8 reg, u8 data) -{ - int ret; - if(rk610_tv_i2c_client == NULL) - return -1; - ret = i2c_master_reg8_send(rk610_tv_i2c_client, reg, &data, 1, RK610_I2C_RATE); - if (ret > 0) - ret = 0; - return ret; -} - -int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode) -{ - struct rk_screen *screen; - - if(modedb == NULL) - return -1; - screen = kzalloc(sizeof(struct rk_screen), GFP_KERNEL); - if(screen == NULL) - return -1; - - memset(screen, 0, sizeof(struct rk_screen)); - /* screen type & face */ - screen->type = SCREEN_HDMI; - screen->mode = modedb->vmode; - screen->face = modedb->flag; - /* Screen size */ - screen->x_res = modedb->xres; - screen->y_res = modedb->yres; - - /* Timing */ - screen->pixclock = modedb->pixclock; - - screen->lcdc_aclk = 500000000; - screen->left_margin = modedb->left_margin; - screen->right_margin = modedb->right_margin; - screen->hsync_len = modedb->hsync_len; - screen->upper_margin = modedb->upper_margin; - screen->lower_margin = modedb->lower_margin; - screen->vsync_len = modedb->vsync_len; - - /* Pin polarity */ - if(FB_SYNC_HOR_HIGH_ACT & modedb->sync) - screen->pin_hsync = 1; - else - screen->pin_hsync = 0; - if(FB_SYNC_VERT_HIGH_ACT & modedb->sync) - screen->pin_vsync = 1; - else - screen->pin_vsync = 0; - screen->pin_den = 0; - screen->pin_dclk = 0; - - /* Swap rule */ - screen->swap_rb = 0; - screen->swap_rg = 0; - screen->swap_gb = 0; - screen->swap_delta = 0; - screen->swap_dumy = 0; - - /* Operation function*/ - screen->init = NULL; - screen->standby = NULL; - - switch(tv_mode) - { -#ifdef CONFIG_RK610_TVOUT_CVBS - case TVOUT_CVBS_NTSC: - case TVOUT_CVBS_PAL: - screen->init = rk610_tv_cvbs_init;; - break; -#endif - -#ifdef CONFIG_RK610_TVOUT_YPbPr - case TVOUT_YPbPr_720x480p_60: - case TVOUT_YPbPr_720x576p_50: - case TVOUT_YPbPr_1280x720p_50: - case TVOUT_YPbPr_1280x720p_60: - //case TVOUT_YPbPr_1920x1080i_50: - case TVOUT_YPbPr_1920x1080i_60: - case TVOUT_YPbPr_1920x1080p_50: - case TVOUT_YPbPr_1920x1080p_60: - screen->init = rk610_tv_ypbpr_init; - break; -#endif - default:{ - kfree(screen); - return -1; - } - break; - } - rk610_tv_output_status = tv_mode; - FB_Switch_Screen(screen, 1); - kfree(screen); - return 0; -} - -int rk610_tv_standby(int type) -{ - int ret; - - switch(type) - { - #ifdef CONFIG_RK610_TVOUT_CVBS - case RK610_TVOUT_CVBS: - if(rk610_cvbs_monspecs.enable == 0) - return 0; - #ifdef CONFIG_RK610_TVOUT_YPbPr - if(rk610_ypbpr_monspecs.enable == 1) - return 0; - #endif - break; - #endif - #ifdef CONFIG_RK610_TVOUT_YPbPr - case RK610_TVOUT_YPBPR: - if(rk610_ypbpr_monspecs.enable == 0) - return 0; - #ifdef CONFIG_RK610_TVOUT_CVBS - if(rk610_cvbs_monspecs.enable == 1) - return 0; - #endif - break; - #endif - default: - break; - } - - ret = rk610_tv_wirte_reg(TVE_POWERCR, 0); - if(ret < 0){ - printk("[%s] rk610_tv_wirte_reg err!\n", __FUNCTION__); - return ret; - } - - ret = rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, 0); - if(ret < 0){ - printk("[%s] rk610_control_send_byte err!\n", __FUNCTION__); - return ret; - } - return 0; -} - -static int rk610_tv_probe(struct i2c_client *client,const struct i2c_device_id *id) -{ - int rc = 0; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - rc = -ENODEV; - goto failout; - } - rk610_tv_i2c_client = client; - -#ifdef CONFIG_RK610_TVOUT_YPbPr - rk610_register_display_ypbpr(&client->dev); - if(rk610_tv_output_status > TVOUT_CVBS_PAL) - rk_display_device_enable(rk610_ypbpr_monspecs.ddev); -#endif - -#ifdef CONFIG_RK610_TVOUT_CVBS - rk610_register_display_cvbs(&client->dev); - if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) - rk_display_device_enable(rk610_cvbs_monspecs.ddev); -#endif - - printk(KERN_INFO "rk610_tv ver 1.0 probe ok\n"); - return 0; -failout: - kfree(client); - return rc; -} - -static int rk610_tv_remove(struct i2c_client *client) -{ - return 0; -} - - -static const struct i2c_device_id rk610_tv_id[] = { - { DRV_NAME, 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, rk610_tv_id); - -static struct i2c_driver rk610_tv_driver = { - .driver = { - .name = DRV_NAME, - }, - .id_table = rk610_tv_id, - .probe = rk610_tv_probe, - .remove = rk610_tv_remove, -}; - -static int __init rk610_tv_init(void) -{ - int ret = 0; - ret = i2c_add_driver(&rk610_tv_driver); - if(ret < 0){ - printk("i2c_add_driver err, ret = %d\n", ret); - } - return ret; -} - -static void __exit rk610_tv_exit(void) -{ - i2c_del_driver(&rk610_tv_driver); -} - -module_init(rk610_tv_init); -//late_initcall(rk610_tv_init); -module_exit(rk610_tv_exit); - -/* Module information */ -MODULE_DESCRIPTION("ROCKCHIP RK610 TV Output"); -MODULE_LICENSE("GPL"); - - diff --git a/drivers/video/rockchip/tve/rk610_tv.h b/drivers/video/rockchip/tve/rk610_tv.h deleted file mode 100644 index ead23a8a06a1..000000000000 --- a/drivers/video/rockchip/tve/rk610_tv.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef _RK610_TV_H -#define _RK610_TV_H -#include -#include -#include -#include -#ifdef CONFIG_ARCH_RK29 -#include -#endif -#include "../screen/screen.h" -#include "../../rk29_fb.h" -#include - -#define TVE_VFCR 0x00 - #define TVE_VFCR_ENABLE_SUBCARRIER_RESET 0 << 6 - #define TVE_VFCR_DISABLE_SUBCARRIER_RESET 1 << 6 - #define TVE_VFCR_VIN_RANGE_16_235 0 << 3 - #define TVE_VFCR_VIN_RANGE_1_254 1 << 3 - #define TVE_VFCR_BLACK_7_5_IRE 0 << 2 - #define TVE_VFCR_BLACK_0_IRE 1 << 2 - #define TVE_VFCR_NTSC 0 - #define TVE_VFCR_PAL_M 1 - #define TVE_VFCR_PAL_B_N 2 - #define TVE_VFCR_PAL_NC 3 - -#define TVE_VINCR 0x01 - #define TVE_VINCR_PIX_DATA_DELAY(n) (n << 5) - #define TVE_VINCR_H_SYNC_POLARITY_NEGTIVE 0 << 4 - #define TVE_VINCR_H_SYNC_POLARITY_POSITIVE 1 << 4 - #define TVE_VINCR_V_SYNC_POLARITY_NEGTIVE 0 << 3 - #define TVE_VINCR_V_SYNC_POLARITY_POSITIVE 1 << 3 -enum { - INPUT_FORMAT_BT601_SLAVE = 0, - INPUT_FORMAT_BT656, - INPUT_FORMAT_BT601_MASTER, - INPUT_FORMAT_INTERNAL_COLLOR_BAR -}; - #define TVE_VINCR_INPUT_FORMAT(n) (n << 1) - #define TVE_VINCR_VSYNC_FUNCTION_VSYNC 0 - #define TVE_VINCR_VSYNC_FUNCTION_FIELD 1 - -#define TVE_VOUTCR 0x02 - #define TVE_VOUTCR_OUTPUT_CVBS 0 << 6 - #define TVE_VOUTCR_OUTPUT_YPBPR 1 << 6 - #define TVE_VOUTCR_OUTPUT_ENABLE_BLUE 1 << 5 - #define TVE_VOUTCR_OUTPUT_ENABLE_BLACK 1 << 4 - #define TVE_VOUTCR_DISABLE_CVBS_COLOR 1 << 3 - #define TVE_VOUTCR_CVBS_Y2C_DELAY(n) (n << 0) - -#define TVE_POWERCR 0x03 - #define TVE_PIX_CLK_INVERSE_ENABLE 1 << 4 - #define TVE_DAC_CLK_INVERSE_DISABLE 1 << 3 - #define TVE_DAC_Y_ENABLE 1 << 2 - #define TVE_DAC_U_ENABLE 1 << 1 - #define TVE_DAC_V_ENABLE 1 << 0 - -#define TVE_HDTVCR 0x05 - #define TVE_RESET 1 << 7 - #define TVE_FILTER(n) (n << 5) - #define TVE_COLOR_CONVERT_REC601 0 << 4 - #define TVE_COLOR_CONVERT_REC709 1 << 4 - #define TVE_INPUT_DATA_RGB 0 << 3 - #define TVE_INPUT_DATA_YUV 1 << 3 - #define TVE_OUTPUT_50HZ 0 << 2 - #define TVE_OUTPUT_60HZ 1 << 2 - #define TVE_OUTPUT_MODE_PAL_NTSC 0 - #define TVE_OUTPUT_MODE_576P 1 - #define TVE_OUTPUT_MODE_480P 2 - #define TVE_OUTPUT_MODE_720P 3 - -#define TVE_YADJCR 0x06 - #define TVE_OUTPUT_MODE_1080P 1 << 6 - #define TVE_OUTPUT_MODE_1080I 1 << 5 - #define TVE_Y_ADJ_VALUE(n) n -#define TVE_YCBADJCR 0x07 -#define TVE_YCRADJCR 0x08 - -/******************* TVOUT OUTPUT TYPE **********************/ -struct rk610_monspecs { - struct rk_display_device *ddev; - unsigned int enable; - struct fb_videomode *mode; - struct list_head modelist; - unsigned int mode_set; -}; - -enum { - TVOUT_CVBS_NTSC = 1, - TVOUT_CVBS_PAL, - TVOUT_YPbPr_720x480p_60, - TVOUT_YPbPr_720x576p_50, - TVOUT_YPbPr_1280x720p_50, - TVOUT_YPbPr_1280x720p_60, - //TVOUT_YPbPr_1920x1080i_50, - TVOUT_YPbPr_1920x1080i_60, - TVOUT_YPbPr_1920x1080p_50, - TVOUT_YPbPr_1920x1080p_60 -}; - -#define RK610_TVOUT_DEAULT TVOUT_CVBS_NTSC - -enum { - RK610_TVOUT_CVBS = 0, - RK610_TVOUT_YC, - RK610_TVOUT_YPBPR, -}; - -extern volatile int rk610_tv_output_status; -extern struct rk_display_ops rk610_display_ops; - -extern int FB_Switch_Screen( struct rk_screen *screen, u32 enable ); - -extern int rk610_tv_wirte_reg(u8 reg, u8 data); -extern int rk610_tv_standby(int type); -extern int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode); -extern int rk610_register_display(struct device *parent); - -#ifdef CONFIG_RK610_TVOUT_YPbPr -extern int rk610_tv_ypbpr_init(void); -extern int rk610_register_display_ypbpr(struct device *parent); -extern struct rk610_monspecs rk610_ypbpr_monspecs; -#endif - -#ifdef CONFIG_RK610_TVOUT_CVBS -extern int rk610_tv_cvbs_init(void); -extern int rk610_register_display_cvbs(struct device *parent); -extern struct rk610_monspecs rk610_cvbs_monspecs; -#endif - -#endif - diff --git a/drivers/video/rockchip/tve/rk610_tv_cvbs.c b/drivers/video/rockchip/tve/rk610_tv_cvbs.c deleted file mode 100644 index ea0fe8a0d79c..000000000000 --- a/drivers/video/rockchip/tve/rk610_tv_cvbs.c +++ /dev/null @@ -1,209 +0,0 @@ -#include -#include -#include -#include "rk610_tv.h" - - -#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL -#define RK610_LED_CVBS_PIN RK29_PIN4_PD3 -#else -#define RK610_LED_CVBS_PIN INVALID_GPIO -#endif - -#ifdef USE_RGB2CCIR -static const struct fb_videomode rk610_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, 116, 16, 25, 14, 6, 6, 0, 1, OUT_P888 }, - { "PAL", 50, 720, 576, 27000000, 126, 12, 37, 6, 6, 6, 0, 1, OUT_P888 }, -}; -#else -static const struct fb_videomode rk610_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, 116, 16, 16, 3, 6, 3, 0, 1, OUT_CCIR656 }, - { "PAL", 50, 720, 576, 27000000, 126, 12, 19, 2, 6, 3, 0, 1, OUT_CCIR656 }, -}; -#endif - -struct rk610_monspecs rk610_cvbs_monspecs; - - -int rk610_tv_cvbs_init(void) -{ - unsigned char TVE_Regs[9]; - unsigned char TVE_CON_Reg; - int ret, i; - - rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET); - - memset(TVE_Regs, 0, 9); - TVE_CON_Reg = TVE_CONTROL_CVBS_3_CHANNEL_ENALBE; - TVE_Regs[TVE_VINCR] = TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC; - TVE_Regs[TVE_POWERCR] = TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE; - TVE_Regs[TVE_VOUTCR] = TVE_VOUTCR_OUTPUT_CVBS; - TVE_Regs[TVE_YADJCR] = 0x17; - TVE_Regs[TVE_YCBADJCR] = 0x10; - TVE_Regs[TVE_YCRADJCR] = 0x10; - - switch(rk610_tv_output_status) { - case TVOUT_CVBS_NTSC: - TVE_Regs[TVE_VFCR] = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_7_5_IRE | TVE_VFCR_NTSC; - #ifdef USE_RGB2CCIR - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC; - TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_NTSC | RGB2CCIR_ENABLE; - #else - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC; - #endif - break; - case TVOUT_CVBS_PAL: - TVE_Regs[TVE_VFCR] = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_B_N; - #ifdef USE_RGB2CCIR - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC; - TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_PAL | RGB2CCIR_ENABLE; - #else - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC; - #endif - break; - default: - return -1; - } - - for(i = 0; i < sizeof(TVE_Regs); i++){ -// printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]); - ret = rk610_tv_wirte_reg(i, TVE_Regs[i]); - if(ret < 0){ - printk(KERN_ERR "rk610_tv_wirte_reg %d err!\n", i); - return ret; - } - } -// printk(KERN_ERR "TVE_CON_Reg = 0x%02x\n", TVE_CON_Reg); - rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg); - #ifdef USE_RGB2CCIR - rk610_control_send_byte(RK610_CONTROL_REG_CCIR_RESET, 0x01); - #endif - return 0; -} - -static int rk610_cvbs_set_enable(struct rk_display_device *device, int enable) -{ - if(rk610_cvbs_monspecs.enable != enable || rk610_cvbs_monspecs.mode_set != rk610_tv_output_status) - { - if(enable == 0) - { - rk610_tv_standby(RK610_TVOUT_CVBS); - rk610_cvbs_monspecs.enable = 0; - if(RK610_LED_CVBS_PIN != INVALID_GPIO) - gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH); - } - else if(enable == 1) - { - rk610_switch_fb(rk610_cvbs_monspecs.mode, rk610_cvbs_monspecs.mode_set); - rk610_cvbs_monspecs.enable = 1; - if(RK610_LED_CVBS_PIN != INVALID_GPIO) - gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_LOW); - } - } - return 0; -} - -static int rk610_cvbs_get_enable(struct rk_display_device *device) -{ - return rk610_cvbs_monspecs.enable; -} - -static int rk610_cvbs_get_status(struct rk_display_device *device) -{ - if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) - return 1; - else - return 0; -} - -static int rk610_cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist) -{ - *modelist = &(rk610_cvbs_monspecs.modelist); - return 0; -} - -static int rk610_cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode) -{ - int i; - - for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++) - { - if(fb_mode_is_equal(&rk610_cvbs_mode[i], mode)) - { - if( ((i + 1) != rk610_tv_output_status) ) - { - rk610_cvbs_monspecs.mode_set = i + 1; - rk610_cvbs_monspecs.mode = (struct fb_videomode *)&rk610_cvbs_mode[i]; - } - return 0; - } - } - - return -1; -} - -static int rk610_cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode) -{ - *mode = *(rk610_cvbs_monspecs.mode); - return 0; -} - -static struct rk_display_ops rk610_cvbs_display_ops = { - .setenable = rk610_cvbs_set_enable, - .getenable = rk610_cvbs_get_enable, - .getstatus = rk610_cvbs_get_status, - .getmodelist = rk610_cvbs_get_modelist, - .setmode = rk610_cvbs_set_mode, - .getmode = rk610_cvbs_get_mode, -}; - -static int rk610_display_cvbs_probe(struct rk_display_device *device, void *devdata) -{ - device->owner = THIS_MODULE; - strcpy(device->type, "TV"); - device->priority = DISPLAY_PRIORITY_TV; - device->priv_data = devdata; - device->ops = &rk610_cvbs_display_ops; - return 1; -} - -static struct rk_display_driver display_rk610_cvbs = { - .probe = rk610_display_cvbs_probe, -}; - -int rk610_register_display_cvbs(struct device *parent) -{ - int i; - - memset(&rk610_cvbs_monspecs, 0, sizeof(struct rk610_monspecs)); - INIT_LIST_HEAD(&rk610_cvbs_monspecs.modelist); - for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++) - fb_add_videomode(&rk610_cvbs_mode[i], &rk610_cvbs_monspecs.modelist); - if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) { - rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[rk610_tv_output_status - 1]); - rk610_cvbs_monspecs.mode_set = rk610_tv_output_status; - } - else { - rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[0]); - rk610_cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC; - } - rk610_cvbs_monspecs.ddev = rk_display_device_register(&display_rk610_cvbs, parent, NULL); - if(RK610_LED_CVBS_PIN != INVALID_GPIO) - { - if(gpio_request(RK610_LED_CVBS_PIN, NULL) != 0) - { - gpio_free(RK610_LED_CVBS_PIN); - dev_err(rk610_cvbs_monspecs.ddev->dev, ">>>>>> RK610_LED_CVBS_PIN gpio_request err \n "); - return -1; - } - gpio_pull_updown(RK610_LED_CVBS_PIN,GPIOPullUp); - gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH); - } - return 0; -} diff --git a/drivers/video/rockchip/tve/rk610_tv_ypbpr.c b/drivers/video/rockchip/tve/rk610_tv_ypbpr.c deleted file mode 100644 index af74126f7604..000000000000 --- a/drivers/video/rockchip/tve/rk610_tv_ypbpr.c +++ /dev/null @@ -1,229 +0,0 @@ -#include -#include -#include -#include "rk610_tv.h" - - -#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL -#define RK610_LED_YPbPr_PIN RK29_PIN4_PD5 -#else -#define RK610_LED_YPbPr_PIN INVALID_GPIO -#endif -#define E(fmt, arg...) printk("<3>!!!%s:%d: " fmt, __FILE__, __LINE__, ##arg) - -static const struct fb_videomode rk610_YPbPr_mode [] = { - //name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag - { "YPbPr480p", 60, 720, 480, 27000000, 55, 19, 37, 5, 64, 5, 0, 0, OUT_P888 }, - { "YPbPr576p", 50, 720, 576, 27000000, 68, 12, 39, 5, 64, 5, 0, 0, OUT_P888 }, - { "YPbPr720p@50", 50, 1280, 720, 74250000, 600, 0, 20, 5, 100, 5, 0, 0, OUT_P888 }, - { "YPbPr720p@60", 60, 1280, 720, 74250000, 270, 0, 20, 5, 100, 5, 0, 0, OUT_P888 }, - //{ "YPbPr1080i@50", 50, 1920, 1080, 148500000, 620, 0, 15, 2, 100, 5, 0, 1, OUT_CCIR656 }, - { "YPbPr1080i@60", 60, 1920, 1080, 148500000, 180, 0, 15, 2, 100, 5, 0, 1, OUT_CCIR656 }, - { "YPbPr1080p@50", 50, 1920, 1080, 148500000, 620, 0, 36, 4, 100, 5, 0, 0, OUT_P888 }, - { "YPbPr1080p@60", 60, 1920, 1080, 148500000, 180, 0, 36, 4, 100, 5, 0, 0, OUT_P888 }, -}; - -struct rk610_monspecs rk610_ypbpr_monspecs; - -int rk610_tv_ypbpr_init(void) -{ - unsigned char TVE_Regs[9]; - unsigned char TVE_CON_Reg; - int i, ret; - - rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET); - memset(TVE_Regs, 0, 9); - - TVE_CON_Reg = 0x00; - - TVE_Regs[TVE_VINCR] = TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC; - TVE_Regs[TVE_POWERCR] = TVE_DAC_CLK_INVERSE_DISABLE | TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE; - TVE_Regs[TVE_VOUTCR] = TVE_VOUTCR_OUTPUT_YPBPR; - TVE_Regs[TVE_YADJCR] = 0x17; - TVE_Regs[TVE_YCBADJCR] = 0x10; - TVE_Regs[TVE_YCRADJCR] = 0x10; - - switch(rk610_tv_output_status) - { - case TVOUT_YPbPr_720x480p_60: - TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE; - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_480P; - break; - case TVOUT_YPbPr_720x576p_50: - TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_576P; - break; - case TVOUT_YPbPr_1280x720p_50: - TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_720P; - break; - case TVOUT_YPbPr_1280x720p_60: - TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_720P; - break; - /*case TVOUT_YPbPr_1920x1080i_50: - TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_50HZ; - TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080I; - break; - */ - case TVOUT_YPbPr_1920x1080i_60: - TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_60HZ; - TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080I; - break; - case TVOUT_YPbPr_1920x1080p_50: - TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ; - TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080P; - break; - case TVOUT_YPbPr_1920x1080p_60: - TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; - TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); - TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ; - TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080P; - break; - default: - return -1; - } - - rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg); - - for(i = 0; i < sizeof(TVE_Regs); i++){ -// printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]); - ret = rk610_tv_wirte_reg(i, TVE_Regs[i]); - if(ret < 0){ - E("rk610_tv_wirte_reg %d err!\n", i); - return ret; - } - } - return 0; -} - -static int rk610_ypbpr_set_enable(struct rk_display_device *device, int enable) -{ - if(rk610_ypbpr_monspecs.enable != enable || rk610_ypbpr_monspecs.mode_set != rk610_tv_output_status) - { - if(enable == 0) - { - rk610_tv_standby(RK610_TVOUT_YPBPR); - rk610_ypbpr_monspecs.enable = 0; - if(RK610_LED_YPbPr_PIN != INVALID_GPIO) - gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH); - } - else if(enable == 1) - { - rk610_switch_fb(rk610_ypbpr_monspecs.mode, rk610_ypbpr_monspecs.mode_set); - rk610_ypbpr_monspecs.enable = 1; - if(RK610_LED_YPbPr_PIN != INVALID_GPIO) - gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_LOW); - } - } - return 0; -} - -static int rk610_ypbpr_get_enable(struct rk_display_device *device) -{ - return rk610_ypbpr_monspecs.enable; -} - -static int rk610_ypbpr_get_status(struct rk_display_device *device) -{ - if(rk610_tv_output_status > TVOUT_CVBS_PAL) - return 1; - else - return 0; -} - -static int rk610_ypbpr_get_modelist(struct rk_display_device *device, struct list_head **modelist) -{ - *modelist = &(rk610_ypbpr_monspecs.modelist); - return 0; -} - -static int rk610_ypbpr_set_mode(struct rk_display_device *device, struct fb_videomode *mode) -{ - int i; - - for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++) - { - if(fb_mode_is_equal(&rk610_YPbPr_mode[i], mode)) - { - if( (i + 3) != rk610_tv_output_status ) - { - rk610_ypbpr_monspecs.mode_set = i + 3; - rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&rk610_YPbPr_mode[i]; - } - return 0; - } - } - - return -1; -} - -static int rk610_ypbpr_get_mode(struct rk_display_device *device, struct fb_videomode *mode) -{ - *mode = *(rk610_ypbpr_monspecs.mode); - return 0; -} - -static struct rk_display_ops rk610_ypbpr_display_ops = { - .setenable = rk610_ypbpr_set_enable, - .getenable = rk610_ypbpr_get_enable, - .getstatus = rk610_ypbpr_get_status, - .getmodelist = rk610_ypbpr_get_modelist, - .setmode = rk610_ypbpr_set_mode, - .getmode = rk610_ypbpr_get_mode, -}; - -static int rk610_display_YPbPr_probe(struct rk_display_device *device, void *devdata) -{ - device->owner = THIS_MODULE; - strcpy(device->type, "YPbPr"); - device->priority = DISPLAY_PRIORITY_YPbPr; - device->priv_data = devdata; - device->ops = &rk610_ypbpr_display_ops; - return 1; -} - -static struct rk_display_driver display_rk610_YPbPr = { - .probe = rk610_display_YPbPr_probe, -}; - -int rk610_register_display_ypbpr(struct device *parent) -{ - int i; - - memset(&rk610_ypbpr_monspecs, 0, sizeof(struct rk610_monspecs)); - INIT_LIST_HEAD(&rk610_ypbpr_monspecs.modelist); - for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++) - fb_add_videomode(&rk610_YPbPr_mode[i], &rk610_ypbpr_monspecs.modelist); - if(rk610_tv_output_status > TVOUT_CVBS_PAL) { - rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[rk610_tv_output_status - 3]); - rk610_ypbpr_monspecs.mode_set = rk610_tv_output_status; - } - else { - rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[3]); - rk610_ypbpr_monspecs.mode_set = TVOUT_YPbPr_1280x720p_60; - } - rk610_ypbpr_monspecs.ddev = rk_display_device_register(&display_rk610_YPbPr, parent, NULL); - if(RK610_LED_YPbPr_PIN != INVALID_GPIO) - { - if(gpio_request(RK610_LED_YPbPr_PIN, NULL) != 0) - { - gpio_free(RK610_LED_YPbPr_PIN); - dev_err(rk610_ypbpr_monspecs.ddev->dev, ">>>>>> RK610_LED_YPbPr_PIN gpio_request err \n "); - return -1; - } - gpio_pull_updown(RK610_LED_YPbPr_PIN,GPIOPullUp); - gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH); - } - return 0; -} diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index 37da53946f80..da1e03cae33a 100755 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -342,6 +342,7 @@ struct rk_lcdc_win_area{ struct rk_lcdc_win { char name[5]; int id; + u32 logicalstate; bool state; /*on or off*/ bool last_state; /*on or off*/ u32 pseudo_pal[16]; @@ -546,8 +547,11 @@ struct rk_lcdc_driver { char fb1_win_id; char fb2_win_id; char fb3_win_id; + char mmu_dts_name[40]; + struct device *mmu_dev; int iommu_enabled; + struct rk_fb_reg_area_data reg_area_data; struct mutex fb_win_id_mutex; @@ -576,7 +580,7 @@ struct rk_lcdc_driver { #ifdef CONFIG_DRM_ROCKCHIP void (*irq_call_back)(struct rk_lcdc_driver *driver); #endif - + struct overscan overscan; }; /*disp_mode: dual display mode