/dts-v1/;
-
+#include <dt-bindings/rkfb/rk_fb.h>
#include "rk3036.dtsi"
#include "rk3036-pinctrl.dtsi"
+#include "lcd-box.dtsi"
/ {
fiq-debugger {
//irq_gpio = <&gpio0 GPIO_A4 IRQ_TYPE_EDGE_FALLING>;
};
};
+
+
+&rk_screen {
+ display-timings = <&disp_timings>;
+};
+
+&lcdc {
+ status = "okay";
+};
clock-names = "clk_usbphy1", "hclk_usb1";
};
+ fb: fb{
+ compatible = "rockchip,rk-fb";
+ rockchip,disp-mode = <NO_DUAL>;
+ };
+
+ rk_screen: rk_screen{
+ compatible = "rockchip,screen";
+ };
+
lcdc: lcdc@10118000 {
compatible = "rockchip,rk3036-lcdc";
reg = <0x10118000 0x4000>;
- interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
clocks = <&clk_gates9 6>, <&dclk_lcdc1>, <&clk_gates9 5>;
clock-names = "aclk_lcdc", "dclk_lcdc", "hclk_lcdc";
status = "disabled";
};
+ tve {
+ compatible = "rockchip,rk3036-tve";
+ reg = <0x10118200 0x100>;
+ status = "disabled";
+ };
+
vpu: vpu_service@10108000 {
compatible = "vpu_service";
reg = <0x10108000 0x800>;
obj-$(CONFIG_ROCKCHIP_RGA2) += rga2/
obj-$(CONFIG_RK_HDMI) += display-sys.o hdmi/
obj-$(CONFIG_IEP) += iep/
+obj-$(CONFIG_RK_TVENCODER) += tve/
+
#include <linux/rockchip/grf.h>
#include <linux/rockchip/common.h>
#include <dt-bindings/clock/rk_system_status.h>
-
+#if defined(CONFIG_ION_ROCKCHIP)
+#include <linux/rockchip/iovmm.h>
+#include <linux/rockchip/sysmmu.h>
+#endif
#include "rk3036_lcdc.h"
static int dbg_thresd;
},
};
-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 =
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)
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);
}
+/********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;
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");
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);
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)
{
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);
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);
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);
}
}
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) {
}
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,
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);
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);
{
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;
.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;
}
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;
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);
}
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;
}
#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*/
#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)
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)
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;
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 */
}
}
+ 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;
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)
{
return 0;
}
-
+#endif
int rk_fb_dpi_open(bool open)
{
struct rk_lcdc_driver *dev_drv = NULL;
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
return 0;
}
-
+#endif
/*
* function:this function current only called by hdmi for
* scale the display
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;
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;
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 =
"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) {
-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
#
-# 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/
--- /dev/null
+config RK3036_TV_ENCODER
+ bool "rk3036 tv encoder support"
+ depends on LCDC_RK3036
+ default n
+ help
+ Support RK3036 output CVBS.
+
--- /dev/null
+#
+# Makefile for the rk3036 tv encoder control.
+#
+obj-$(CONFIG_RK3036_TV_ENCODER) += rk3036_tve.o
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/rk_fb.h>
+#include <linux/display-sys.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/iomap.h>
+#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
--- /dev/null
+#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
--- /dev/null
+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
--- /dev/null
+#
+# 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
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <asm/uaccess.h>
+#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");
+
+
--- /dev/null
+#ifndef _RK610_TV_H
+#define _RK610_TV_H
+#include <linux/display-sys.h>
+#include <linux/rk_fb.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#ifdef CONFIG_ARCH_RK29
+#include <mach/rk29_iomap.h>
+#endif
+#include "../screen/screen.h"
+#include "../../rk29_fb.h"
+#include <linux/mfd/rk610_core.h>
+
+#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
+
--- /dev/null
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/display-sys.h>
+#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;
+}
--- /dev/null
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/display-sys.h>
+#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;
+}
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/fcntl.h>
-#include <linux/fs.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <asm/uaccess.h>
-#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");
-
-
+++ /dev/null
-#ifndef _RK610_TV_H
-#define _RK610_TV_H
-#include <linux/display-sys.h>
-#include <linux/rk_fb.h>
-#include <mach/board.h>
-#include <mach/gpio.h>
-#ifdef CONFIG_ARCH_RK29
-#include <mach/rk29_iomap.h>
-#endif
-#include "../screen/screen.h"
-#include "../../rk29_fb.h"
-#include <linux/mfd/rk610_core.h>
-
-#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
-
+++ /dev/null
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/display-sys.h>
-#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;
-}
+++ /dev/null
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/display-sys.h>
-#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;
-}
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];
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;
#ifdef CONFIG_DRM_ROCKCHIP
void (*irq_call_back)(struct rk_lcdc_driver *driver);
#endif
-
+ struct overscan overscan;
};
/*disp_mode: dual display mode