rockchip: video: vop: Reserve enough space for mipi dispaly
[platform/kernel/u-boot.git] / drivers / video / rockchip / rk_vop.c
index db09d9a..aa6ca8c 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/arch/cru_rk3288.h>
 #include <asm/arch/grf_rk3288.h>
 #include <asm/arch/edp_rk3288.h>
-#include <asm/arch/hdmi_rk3288.h>
 #include <asm/arch/vop_rk3288.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
@@ -118,6 +117,10 @@ void rkvop_mode_set(struct rk3288_vop *regs,
                clrsetbits_le32(&regs->sys_ctrl, M_ALL_OUT_EN,
                                V_RGB_OUT_EN(1));
                break;
+       case VOP_MODE_MIPI:
+               clrsetbits_le32(&regs->sys_ctrl, M_ALL_OUT_EN,
+                               V_MIPI_OUT_EN(1));
+                break;
        }
 
        if (mode == VOP_MODE_HDMI || mode == VOP_MODE_EDP)
@@ -178,13 +181,11 @@ void rkvop_mode_set(struct rk3288_vop *regs,
  *
  * @dev:       VOP device that we want to connect to the display
  * @fbbase:    Frame buffer address
- * @l2bpp      Log2 of bits-per-pixels for the display
  * @ep_node:   Device tree node to process - this is the offset of an endpoint
  *             node within the VOP's 'port' list.
  * @return 0 if OK, -ve if something went wrong
  */
-int rk_display_init(struct udevice *dev, ulong fbbase,
-                   enum video_log2_bpp l2bpp, int ep_node)
+int rk_display_init(struct udevice *dev, ulong fbbase, int ep_node)
 {
        struct video_priv *uc_priv = dev_get_uclass_priv(dev);
        const void *blob = gd->fdt_blob;
@@ -195,7 +196,8 @@ int rk_display_init(struct udevice *dev, ulong fbbase,
        struct udevice *disp;
        int ret, remote, i, offset;
        struct display_plat *disp_uc_plat;
-       struct udevice *clk;
+       struct clk clk;
+       enum video_log2_bpp l2bpp;
 
        vop_id = fdtdec_get_int(blob, ep_node, "reg", -1);
        debug("vop_id=%d\n", vop_id);
@@ -221,6 +223,11 @@ int rk_display_init(struct udevice *dev, ulong fbbase,
 
        disp_uc_plat = dev_get_uclass_platdata(disp);
        debug("Found device '%s', disp_uc_priv=%p\n", disp->name, disp_uc_plat);
+       if (display_in_use(disp)) {
+               debug("   - device in use\n");
+               return -EBUSY;
+       }
+
        disp_uc_plat->source_id = remote_vop_id;
        disp_uc_plat->src_dev = dev;
 
@@ -237,16 +244,27 @@ int rk_display_init(struct udevice *dev, ulong fbbase,
                return ret;
        }
 
-       ret = rkclk_get_clk(CLK_NEW, &clk);
-       if (!ret) {
-               ret = clk_set_periph_rate(clk, DCLK_VOP0 + remote_vop_id,
-                                         timing.pixelclock.typ);
-       }
-       if (ret) {
+       ret = clk_get_by_index(dev, 1, &clk);
+       if (!ret)
+               ret = clk_set_rate(&clk, timing.pixelclock.typ);
+       if (IS_ERR_VALUE(ret)) {
                debug("%s: Failed to set pixel clock: ret=%d\n", __func__, ret);
                return ret;
        }
 
+       /* Set bitwidth for vop display according to vop mode */
+       switch (vop_id) {
+       case VOP_MODE_EDP:
+       case VOP_MODE_HDMI:
+       case VOP_MODE_LVDS:
+               l2bpp = VIDEO_BPP16;
+               break;
+       case VOP_MODE_MIPI:
+               l2bpp = VIDEO_BPP32;
+               break;
+       default:
+               l2bpp = VIDEO_BPP16;
+       }
        rkvop_mode_set(regs, &timing, vop_id);
 
        rkvop_enable(regs, fbbase, 1 << l2bpp, &timing);
@@ -313,14 +331,18 @@ static int rk_vop_probe(struct udevice *dev)
        /*
         * Try all the ports until we find one that works. In practice this
         * tries EDP first if available, then HDMI.
+        *
+        * Note that rockchip_vop_set_clk() always uses NPLL as the source
+        * clock so it is currently not possible to use more than one display
+        * device simultaneously.
         */
-       port = fdt_subnode_offset(blob, dev->of_offset, "port");
+       port = fdt_subnode_offset(blob, dev_of_offset(dev), "port");
        if (port < 0)
                return -EINVAL;
        for (node = fdt_first_subnode(blob, port);
             node > 0;
             node = fdt_next_subnode(blob, node)) {
-               ret = rk_display_init(dev, plat->base, VIDEO_BPP16, node);
+               ret = rk_display_init(dev, plat->base, node);
                if (ret)
                        debug("Device failed: ret=%d\n", ret);
                if (!ret)
@@ -335,7 +357,7 @@ static int rk_vop_bind(struct udevice *dev)
 {
        struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
 
-       plat->size = 1920 * 1080 * 2;
+       plat->size = 1920 * 1200 * 4;
 
        return 0;
 }
@@ -344,6 +366,8 @@ static const struct video_ops rk_vop_ops = {
 };
 
 static const struct udevice_id rk_vop_ids[] = {
+       { .compatible = "rockchip,rk3399-vop-big" },
+       { .compatible = "rockchip,rk3399-vop-lit" },
        { .compatible = "rockchip,rk3288-vop" },
        { }
 };