MLK-14286-6 video: mipi_dsi_northwest: add encoder support in dsi
authorFancy Fang <chen.fang@nxp.com>
Tue, 28 Feb 2017 08:16:08 +0000 (16:16 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:21:51 +0000 (15:21 -0500)
The northwest mipi dsi on imx7ulp board has an ADV7535 dsi-to-hdmi
encoder. Enable the encoder support in the dsi driver.

Signed-off-by: Fancy Fang <chen.fang@nxp.com>
(cherry picked from commit a6e2da1935d893860cd389ce8360e89434f5fd50)

drivers/video/fbdev/mxc/mipi_dsi.h
drivers/video/fbdev/mxc/mipi_dsi_northwest.c

index 362c8fc..c3514d9 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP.
  */
 
 /*
@@ -70,6 +71,7 @@ struct mipi_dsi_info {
        const struct mipi_dsi_bus_mux   *bus_mux;
        int                             dsi_power_on;
        int                             lcd_inited;
+       int                             encoder;
        u32                             dphy_pll_config;
        int                             dev_id;
        int                             disp_id;
index dd23f71..a60614c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP.
  *
  * 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
 #include <linux/backlight.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
+#include <linux/of_graph.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
 #include <video/mipi_display.h>
+#include <video/mxc_edid.h>
 #include <linux/mfd/syscon.h>
 
 #include "mipi_dsi.h"
@@ -97,11 +100,48 @@ static int mipi_dsi_dcs_cmd(struct mipi_dsi_info *mipi_dsi,
 static int mipi_dsi_lcd_init(struct mipi_dsi_info *mipi_dsi,
                             struct mxc_dispdrv_setting *setting)
 {
-       int i, size, err;
+       u32 data_lane_num, max_data_rate;
+       int i, size, err = 0;
        struct fb_videomode *mipi_lcd_modedb;
        struct fb_videomode mode;
        struct device *dev = &mipi_dsi->pdev->dev;
 
+       if (mipi_dsi->encoder) {
+               err = of_property_read_u32(dev->of_node,
+                                          "data-lanes-num", &data_lane_num);
+               if (err)
+                       goto err0;
+
+               err = of_property_read_u32(dev->of_node,
+                                          "max-data-rate", &max_data_rate);
+               if (err)
+                       goto err0;
+
+               mipi_dsi->lcd_config->virtual_ch = 0;
+               mipi_dsi->lcd_config->data_lane_num = data_lane_num;
+               mipi_dsi->lcd_config->max_phy_clk = max_data_rate;
+               mipi_dsi->lcd_config->dpi_fmt = MIPI_RGB888;
+               setting->fbi->var.bits_per_pixel = 32;
+
+               /* TODO Add bandwidth check */
+
+               if (setting->fbi->fbops->fb_check_var)
+                       err = setting->fbi->fbops->fb_check_var(&setting->fbi->var,
+                                                               setting->fbi);
+               if (err)
+                       goto err0;
+
+               err = fb_add_videomode(mipi_dsi->mode,
+                                      &setting->fbi->modelist);
+               if (err)
+                       goto err0;
+
+               fb_videomode_to_var(&setting->fbi->var, mipi_dsi->mode);
+               setting->fbi->mode = mipi_dsi->mode;
+       err0:
+               return err;
+       }
+
        for (i = 0; i < ARRAY_SIZE(mipi_dsi_lcd_db); i++) {
                if (!strcmp(mipi_dsi->lcd_panel,
                        mipi_dsi_lcd_db[i].lcd_panel)) {
@@ -256,6 +296,11 @@ static int mipi_dsi_dphy_init(struct mipi_dsi_info *mipi_dsi)
                return -EINVAL;
        }
 
+       if (mipi_dsi->encoder) {
+               if (req_bit_clk > lcd_config->max_phy_clk)
+                       return -EINVAL;
+       }
+
        /* PLL out clock = refclk * CM / (CN * CO)
         * refclock = 24MHz
         * pll vco = 24 * 40 / (3 * 1) = 320MHz
@@ -317,11 +362,13 @@ static int mipi_dsi_host_init(struct mipi_dsi_info *mipi_dsi)
        }
 
        writel(lane_num, mipi_dsi->mmio_base + HOST_CFG_NUM_LANES);
-       writel(0x1, mipi_dsi->mmio_base + HOST_CFG_NONCONTINUOUS_CLK);
+       writel(mipi_dsi->encoder ? 0x0 : 0x1,
+              mipi_dsi->mmio_base + HOST_CFG_NONCONTINUOUS_CLK);
        writel(0x1, mipi_dsi->mmio_base + HOST_CFG_T_PRE);
        writel(52, mipi_dsi->mmio_base + HOST_CFG_T_POST);
        writel(13, mipi_dsi->mmio_base + HOST_CFG_TX_GAP);
-       writel(0x1, mipi_dsi->mmio_base + HOST_CFG_AUTOINSERT_EOTP);
+       writel(mipi_dsi->encoder ? 0x0 : 0x1,
+              mipi_dsi->mmio_base + HOST_CFG_AUTOINSERT_EOTP);
        writel(0x0, mipi_dsi->mmio_base + HOST_CFG_EXTRA_CMDS_AFTER_EOTP);
        writel(0x0, mipi_dsi->mmio_base + HOST_CFG_HTX_TO_COUNT);
        writel(0x0, mipi_dsi->mmio_base + HOST_CFG_LRX_H_TO_COUNT);
@@ -356,7 +403,8 @@ static int mipi_dsi_dpi_init(struct mipi_dsi_info *mipi_dsi)
        writel(pixel_fmt, mipi_dsi->mmio_base + DPI_PIXEL_FORMAT);
        writel(0x0, mipi_dsi->mmio_base + DPI_VSYNC_POLARITY);
        writel(0x0, mipi_dsi->mmio_base + DPI_HSYNC_POLARITY);
-       writel(0x2, mipi_dsi->mmio_base + DPI_VIDEO_MODE);
+       writel(mipi_dsi->encoder ? 0x0 : 0x2,
+              mipi_dsi->mmio_base + DPI_VIDEO_MODE);
 
        writel(mode->right_margin * (bpp >> 3), mipi_dsi->mmio_base + DPI_HFP);
        writel(mode->left_margin * (bpp >> 3), mipi_dsi->mmio_base + DPI_HBP);
@@ -488,23 +536,25 @@ static int mipi_dsi_enable(struct mxc_dispdrv_handle *disp,
                                   DSI_CM, 0x0);
                msleep(20);
 
-               ret = device_reset(&mipi_dsi->pdev->dev);
-               if (ret) {
-                       dev_err(&mipi_dsi->pdev->dev,
-                               "failed to reset device: %d\n", ret);
-                       return -EINVAL;
-               }
-               msleep(60);
+               if (!mipi_dsi->encoder) {
+                       ret = device_reset(&mipi_dsi->pdev->dev);
+                       if (ret) {
+                               dev_err(&mipi_dsi->pdev->dev,
+                                               "failed to reset device: %d\n", ret);
+                               return -EINVAL;
+                       }
+                       msleep(60);
 
-               mipi_dsi_init_interrupt(mipi_dsi);
+                       mipi_dsi_init_interrupt(mipi_dsi);
 
-               ret = mipi_dsi->lcd_callback->mipi_lcd_setup(mipi_dsi);
-               if (ret < 0) {
-                       dev_err(&mipi_dsi->pdev->dev,
-                               "failed to init mipi lcd.\n");
-                       return ret;
+                       ret = mipi_dsi->lcd_callback->mipi_lcd_setup(mipi_dsi);
+                       if (ret < 0) {
+                               dev_err(&mipi_dsi->pdev->dev,
+                                               "failed to init mipi lcd.\n");
+                               return ret;
+                       }
+                       mipi_dsi_set_mode(mipi_dsi, DSI_HS_MODE);
                }
-               mipi_dsi_set_mode(mipi_dsi, DSI_HS_MODE);
 
                mipi_dsi->lcd_inited = 1;
        } else {
@@ -517,10 +567,12 @@ static int mipi_dsi_enable(struct mxc_dispdrv_handle *disp,
 
                reset_dsi_domains(mipi_dsi, 0);
 
-               ret = mipi_display_exit_sleep(mipi_dsi->disp_mipi);
-               if (ret) {
-                       dev_err(&mipi_dsi->pdev->dev, "exit sleep failed\n");
-                       return -EINVAL;
+               if (!mipi_dsi->encoder) {
+                       ret = mipi_display_exit_sleep(mipi_dsi->disp_mipi);
+                       if (ret) {
+                               dev_err(&mipi_dsi->pdev->dev, "exit sleep failed\n");
+                               return -EINVAL;
+                       }
                }
        }
 
@@ -698,7 +750,8 @@ static void mipi_dsi_disable(struct mxc_dispdrv_handle *disp,
 {
        struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
 
-       mipi_display_enter_sleep(mipi_dsi->disp_mipi);
+       if (!mipi_dsi->encoder)
+               mipi_display_enter_sleep(mipi_dsi->disp_mipi);
 
        if (fbi->state == FBINFO_STATE_SUSPENDED) {
                writel(0x1, mipi_dsi->mmio_base + DPHY_PD_PLL);
@@ -785,9 +838,11 @@ static int mipi_dsi_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct mipi_dsi_info *mipi_dsi;
+       struct device_node *endpoint = NULL, *remote;
        struct resource *res;
        const char *lcd_panel;
        int ret = 0;
+       u32 vmode_index;
 
        mipi_dsi = devm_kzalloc(&pdev->dev, sizeof(*mipi_dsi), GFP_KERNEL);
        if (!mipi_dsi)
@@ -830,6 +885,37 @@ static int mipi_dsi_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
+       /* check whether an encoder exists */
+       endpoint = of_graph_get_next_endpoint(np, NULL);
+       if (endpoint) {
+               remote = of_graph_get_remote_port_parent(endpoint);
+               if (!remote)
+                       return -EINVAL;
+
+               ret = of_property_read_u32(remote, "video-mode", &vmode_index);
+               if ((ret < 0) || (vmode_index >= ARRAY_SIZE(mxc_cea_mode)))
+                       return -EINVAL;
+
+               mipi_dsi->mode = devm_kzalloc(&pdev->dev,
+                                             sizeof(struct fb_videomode),
+                                             GFP_KERNEL);
+               if (!mipi_dsi->mode)
+                       return -ENOMEM;
+
+               memcpy(mipi_dsi->mode, &mxc_cea_mode[vmode_index],
+                      sizeof(struct fb_videomode));
+
+               mipi_dsi->lcd_config = devm_kzalloc(&pdev->dev,
+                                               sizeof(struct mipi_lcd_config),
+                                               GFP_KERNEL);
+               if (!mipi_dsi->lcd_config) {
+                       kfree(mipi_dsi->mode);
+                       return -ENOMEM;
+               }
+
+               mipi_dsi->encoder = 1;
+       }
+
        ret = of_property_read_string(np, "lcd_panel", &lcd_panel);
        if (ret) {
                dev_err(&pdev->dev, "failed to read lcd_panel property\n");
@@ -887,7 +973,8 @@ static void mipi_dsi_shutdown(struct platform_device *pdev)
 
        if (mipi_dsi->lcd_inited) {
                clk_prepare_enable(mipi_dsi->esc_clk);
-               mipi_display_enter_sleep(mipi_dsi->disp_mipi);
+               if (!mipi_dsi->encoder)
+                       mipi_display_enter_sleep(mipi_dsi->disp_mipi);
 
                writel(0x1, mipi_dsi->mmio_base + DPHY_PD_PLL);
                writel(0x1, mipi_dsi->mmio_base + DPHY_PD_DPHY);