Commit a4f1e8b67658d4b828d792d5b28cbcf4e7600479

Authored by Ye Li
1 parent 23144983d3

MLK-13929-1 video: Add MIPI DSI host controller driver for i.MX7ULP

Add the host driver base from kernel for MIPI DSI controller on i.MX7ULP.
The controller provides a DPI-2 interface for LCDIF video stream, and a APB interface
for packet transmission.

The driver provides APIs to register a MIPI panel device and its driver. The panel
driver can use the write packet function provided by the host driver to send control
packets to panel device via APB interface.

MIPI DSI has its PHY and dedicated PLL. The driver will setup them when enabling the DSI
host.

Signed-off-by: Ye Li <ye.li@nxp.com>
(cherry picked from commit e02115dd1c5d36ec06eabcb5a0b8e09aaf0f29a0)
(cherry picked from commit 1e984bba8cd961daa4c5bf994a6a90a72cc2f114)

Showing 5 changed files with 816 additions and 0 deletions Side-by-side Diff

drivers/video/Makefile
... ... @@ -62,6 +62,7 @@
62 62 obj-$(CONFIG_VIDEO_CSI) += mxc_csi.o
63 63 obj-$(CONFIG_VIDEO_PXP) += mxc_pxp.o
64 64 obj-$(CONFIG_VIDEO_GIS) += mxc_gis.o
  65 +obj-$(CONFIG_MXC_MIPI_DSI_NORTHWEST) += mipi_dsi_northwest.o
65 66  
66 67 obj-y += bridge/
67 68 obj-y += sunxi/
drivers/video/mipi_dsi_northwest.c
  1 +/*
  2 + * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
  3 + * Copyright 2017 NXP
  4 + *
  5 + * SPDX-License-Identifier: GPL-2.0+
  6 + */
  7 +
  8 +#include <common.h>
  9 +#include <malloc.h>
  10 +
  11 +#include <asm/arch/clock.h>
  12 +#include <asm/arch/sys_proto.h>
  13 +#include <linux/errno.h>
  14 +#include <asm/io.h>
  15 +#include <linux/string.h>
  16 +
  17 +#include "mipi_dsi_northwest_regs.h"
  18 +#include <mipi_dsi_northwest.h>
  19 +#include <mipi_display.h>
  20 +
  21 +#define MIPI_LCD_SLEEP_MODE_DELAY (120)
  22 +#define MIPI_FIFO_TIMEOUT 250000 /* 250ms */
  23 +
  24 +enum mipi_dsi_mode {
  25 + DSI_COMMAND_MODE,
  26 + DSI_VIDEO_MODE
  27 +};
  28 +
  29 +#define DSI_LP_MODE 0
  30 +#define DSI_HS_MODE 1
  31 +
  32 +enum mipi_dsi_payload {
  33 + DSI_PAYLOAD_CMD,
  34 + DSI_PAYLOAD_VIDEO,
  35 +};
  36 +
  37 +/**
  38 + * board_mipi_panel_reset - give a reset cycle for mipi dsi panel
  39 + *
  40 + * Target board specific, like use gpio to reset the dsi panel
  41 + * Machine board file overrides board_mipi_panel_reset
  42 + *
  43 + * Return: 0 Success
  44 + */
  45 +int __weak board_mipi_panel_reset(void)
  46 +{
  47 + return 0;
  48 +}
  49 +
  50 +/**
  51 + * board_mipi_panel_shutdown - Shut down the mipi dsi panel
  52 + *
  53 + * Target board specific, like use gpio to shut down the dsi panel
  54 + * Machine board file overrides board_mipi_panel_shutdown
  55 + *
  56 + * Return: 0 Success
  57 + */
  58 +int __weak board_mipi_panel_shutdown(void)
  59 +{
  60 + return 0;
  61 +}
  62 +
  63 +static void mipi_dsi_set_mode(struct mipi_dsi_northwest_info *mipi_dsi,
  64 + uint8_t mode);
  65 +static int mipi_dsi_dcs_cmd(struct mipi_dsi_northwest_info *mipi_dsi,
  66 + u8 cmd, const u32 *param, int num);
  67 +
  68 +static void mipi_dsi_set_mode(struct mipi_dsi_northwest_info *mipi_dsi,
  69 + uint8_t mode)
  70 +{
  71 + switch (mode) {
  72 + case DSI_LP_MODE:
  73 + writel(0x1, mipi_dsi->mmio_base + HOST_CFG_NONCONTINUOUS_CLK);
  74 + break;
  75 + case DSI_HS_MODE:
  76 + writel(0x0, mipi_dsi->mmio_base + HOST_CFG_NONCONTINUOUS_CLK);
  77 + break;
  78 + default:
  79 + printf("invalid dsi mode\n");
  80 + return;
  81 + }
  82 +
  83 + mdelay(1);
  84 +}
  85 +
  86 +static int mipi_dsi_dphy_init(struct mipi_dsi_northwest_info *mipi_dsi)
  87 +{
  88 + uint32_t time_out = 100;
  89 + uint32_t CN, CM, CO;
  90 + uint32_t lock;
  91 +
  92 + setbits_le32(mipi_dsi->sim_base + SIM_SOPT1, MIPI_ISO_DISABLE);
  93 +
  94 + /* According to the RM, the dpi_pclk and clk_byte frequencies are related by the following formula:
  95 + * clk_byte_freq >= dpi_pclk_freq * DPI_pixel_size / ( 8 * (cfg_num_lanes + 1))
  96 + */
  97 +
  98 + /* PLL out clock = refclk * CM / (CN * CO)
  99 + * refclock = 24MHz
  100 + * pll vco = 24 * 40 / (3 * 1) = 320MHz
  101 + */
  102 + CN = 0x10; /* 3 */
  103 + CM = 0xc8; /* 40 */
  104 + CO = 0x0; /* 1 */
  105 +
  106 + writel(CN, mipi_dsi->mmio_base + DPHY_CN);
  107 + writel(CM, mipi_dsi->mmio_base + DPHY_CM);
  108 + writel(CO, mipi_dsi->mmio_base + DPHY_CO);
  109 +
  110 + writel(0x25, mipi_dsi->mmio_base + DPHY_TST);
  111 + writel(0x0, mipi_dsi->mmio_base + DPHY_PD_PLL);
  112 +
  113 + while (!(lock = readl(mipi_dsi->mmio_base + DPHY_LOCK))) {
  114 + udelay(10);
  115 + time_out--;
  116 + if (time_out == 0) {
  117 + printf("cannot get the dphy lock = 0x%x\n", lock);
  118 + return -EINVAL;
  119 + }
  120 + }
  121 + debug("%s: dphy lock = 0x%x\n", __func__, lock);
  122 +
  123 + writel(0x0, mipi_dsi->mmio_base + DPHY_LOCK_BYP);
  124 + writel(0x1, mipi_dsi->mmio_base + DPHY_RTERM_SEL);
  125 + writel(0x0, mipi_dsi->mmio_base + DPHY_AUTO_PD_EN);
  126 + writel(0x1, mipi_dsi->mmio_base + DPHY_RXLPRP);
  127 + writel(0x1, mipi_dsi->mmio_base + DPHY_RXCDRP);
  128 + writel(0x0, mipi_dsi->mmio_base + DPHY_M_PRG_HS_PREPARE);
  129 + writel(0x0, mipi_dsi->mmio_base + DPHY_MC_PRG_HS_PREPARE);
  130 + writel(0x9, mipi_dsi->mmio_base + DPHY_M_PRG_HS_ZERO);
  131 + writel(0x20, mipi_dsi->mmio_base + DPHY_MC_PRG_HS_ZERO);
  132 + writel(0x5, mipi_dsi->mmio_base + DPHY_M_PRG_HS_TRAIL);
  133 + writel(0x5, mipi_dsi->mmio_base + DPHY_MC_PRG_HS_TRAIL);
  134 + writel(0x0, mipi_dsi->mmio_base + DPHY_PD_DPHY);
  135 +
  136 + setbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_PLL_EN);
  137 + return 0;
  138 +}
  139 +
  140 +static int mipi_dsi_host_init(struct mipi_dsi_northwest_info *mipi_dsi)
  141 +{
  142 + uint32_t lane_num;
  143 +
  144 + switch (mipi_dsi->dsi_panel_dev->data_lane_num) {
  145 + case 1:
  146 + lane_num = 0x0;
  147 + break;
  148 + case 2:
  149 + lane_num = 0x1;
  150 + break;
  151 + default:
  152 + /* Invalid lane num */
  153 + return -EINVAL;
  154 + }
  155 +
  156 + writel(lane_num, mipi_dsi->mmio_base + HOST_CFG_NUM_LANES);
  157 + writel(0x1, mipi_dsi->mmio_base + HOST_CFG_NONCONTINUOUS_CLK);
  158 + writel(0x1, mipi_dsi->mmio_base + HOST_CFG_T_PRE);
  159 + writel(52, mipi_dsi->mmio_base + HOST_CFG_T_POST);
  160 + writel(13, mipi_dsi->mmio_base + HOST_CFG_TX_GAP);
  161 + writel(0x1, mipi_dsi->mmio_base + HOST_CFG_AUTOINSERT_EOTP);
  162 + writel(0x0, mipi_dsi->mmio_base + HOST_CFG_EXTRA_CMDS_AFTER_EOTP);
  163 + writel(0x0, mipi_dsi->mmio_base + HOST_CFG_HTX_TO_COUNT);
  164 + writel(0x0, mipi_dsi->mmio_base + HOST_CFG_LRX_H_TO_COUNT);
  165 + writel(0x0, mipi_dsi->mmio_base + HOST_CFG_BTA_H_TO_COUNT);
  166 + writel(0x3A98, mipi_dsi->mmio_base + HOST_CFG_TWAKEUP);
  167 +
  168 + return 0;
  169 +}
  170 +
  171 +static int mipi_dsi_dpi_init(struct mipi_dsi_northwest_info *mipi_dsi)
  172 +{
  173 + uint32_t bpp, color_coding, pixel_fmt;
  174 + struct fb_videomode *mode = &(mipi_dsi->dsi_panel_dev->mode);
  175 +
  176 + bpp = mipi_dsi->dsi_panel_dev->bpp;
  177 +
  178 + writel(mode->xres, mipi_dsi->mmio_base + DPI_PIXEL_PAYLOAD_SIZE);
  179 + writel(mode->xres, mipi_dsi->mmio_base + DPI_PIXEL_FIFO_SEND_LEVEL);
  180 +
  181 + switch (bpp) {
  182 + case 24:
  183 + color_coding = 5;
  184 + pixel_fmt = 3;
  185 + break;
  186 + case 16:
  187 + case 18:
  188 + default:
  189 + /* Not supported */
  190 + return -EINVAL;
  191 + }
  192 + writel(color_coding, mipi_dsi->mmio_base + DPI_INTERFACE_COLOR_CODING);
  193 + writel(pixel_fmt, mipi_dsi->mmio_base + DPI_PIXEL_FORMAT);
  194 + writel(0x0, mipi_dsi->mmio_base + DPI_VSYNC_POLARITY);
  195 + writel(0x0, mipi_dsi->mmio_base + DPI_HSYNC_POLARITY);
  196 + writel(0x2, mipi_dsi->mmio_base + DPI_VIDEO_MODE);
  197 +
  198 + writel(mode->right_margin * (bpp >> 3), mipi_dsi->mmio_base + DPI_HFP);
  199 + writel(mode->left_margin * (bpp >> 3), mipi_dsi->mmio_base + DPI_HBP);
  200 + writel(mode->hsync_len * (bpp >> 3), mipi_dsi->mmio_base + DPI_HSA);
  201 + writel(0x0, mipi_dsi->mmio_base + DPI_ENABLE_MULT_PKTS);
  202 +
  203 + writel(mode->upper_margin, mipi_dsi->mmio_base + DPI_VBP);
  204 + writel(mode->lower_margin, mipi_dsi->mmio_base + DPI_VFP);
  205 + writel(0x1, mipi_dsi->mmio_base + DPI_BLLP_MODE);
  206 + writel(0x0, mipi_dsi->mmio_base + DPI_USE_NULL_PKT_BLLP);
  207 +
  208 + writel(mode->yres - 1, mipi_dsi->mmio_base + DPI_VACTIVE);
  209 +
  210 + writel(0x0, mipi_dsi->mmio_base + DPI_VC);
  211 +
  212 + return 0;
  213 +}
  214 +
  215 +static void mipi_dsi_init_interrupt(struct mipi_dsi_northwest_info *mipi_dsi)
  216 +{
  217 + /* disable all the irqs */
  218 + writel(0xffffffff, mipi_dsi->mmio_base + HOST_IRQ_MASK);
  219 + writel(0x7, mipi_dsi->mmio_base + HOST_IRQ_MASK2);
  220 +}
  221 +
  222 +static int mipi_display_enter_sleep(struct mipi_dsi_northwest_info *mipi_dsi)
  223 +{
  224 + int err;
  225 +
  226 + err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_SET_DISPLAY_OFF,
  227 + NULL, 0);
  228 + if (err)
  229 + return -EINVAL;
  230 + mdelay(50);
  231 +
  232 + err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_ENTER_SLEEP_MODE,
  233 + NULL, 0);
  234 + if (err)
  235 + printf("MIPI DSI DCS Command sleep in error!\n");
  236 +
  237 + mdelay(MIPI_LCD_SLEEP_MODE_DELAY);
  238 +
  239 + return err;
  240 +}
  241 +
  242 +static int mipi_dsi_enable(struct mipi_dsi_northwest_info *mipi_dsi)
  243 +{
  244 + int ret;
  245 +
  246 + /* Assert resets */
  247 + /* escape domain */
  248 + clrbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_RST_ESC_N);
  249 +
  250 + /* byte domain */
  251 + clrbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_RST_BYTE_N);
  252 +
  253 + /* dpi domain */
  254 + clrbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_RST_DPI_N);
  255 +
  256 + /* Enable mipi relevant clocks */
  257 + enable_mipi_dsi_clk(1);
  258 +
  259 + ret = mipi_dsi_dphy_init(mipi_dsi);
  260 + if (ret < 0)
  261 + return ret;
  262 +
  263 + ret = mipi_dsi_host_init(mipi_dsi);
  264 + if (ret < 0)
  265 + return ret;
  266 +
  267 + ret = mipi_dsi_dpi_init(mipi_dsi);
  268 + if (ret < 0)
  269 + return ret;
  270 +
  271 + /* Deassert resets */
  272 + /* escape domain */
  273 + setbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_RST_ESC_N);
  274 +
  275 + /* byte domain */
  276 + setbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_RST_BYTE_N);
  277 +
  278 + /* dpi domain */
  279 + setbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_RST_DPI_N);
  280 +
  281 + /* display_en */
  282 + clrbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_SD);
  283 +
  284 + /* normal cm */
  285 + clrbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_CM);
  286 + mdelay(20);
  287 +
  288 + /* Reset mipi panel */
  289 + board_mipi_panel_reset();
  290 + mdelay(60);
  291 +
  292 + /* Disable all interrupts, since we use polling */
  293 + mipi_dsi_init_interrupt(mipi_dsi);
  294 +
  295 + /* Call panel driver's setup */
  296 + if (mipi_dsi->dsi_panel_drv->mipi_panel_setup) {
  297 + ret = mipi_dsi->dsi_panel_drv->mipi_panel_setup(mipi_dsi->dsi_panel_dev);
  298 + if (ret < 0) {
  299 + printf("failed to init mipi lcd.\n");
  300 + return ret;
  301 + }
  302 + }
  303 +
  304 + /* Enter the HS mode for video stream */
  305 + mipi_dsi_set_mode(mipi_dsi, DSI_HS_MODE);
  306 +
  307 + return 0;
  308 +}
  309 +
  310 +static void mipi_dsi_wr_tx_header(struct mipi_dsi_northwest_info *mipi_dsi,
  311 + u8 di, u8 data0, u8 data1, u8 mode, u8 need_bta)
  312 +{
  313 + uint32_t pkt_control = 0;
  314 + uint16_t word_count = 0;
  315 +
  316 + word_count = data0 | (data1 << 8);
  317 + pkt_control = HOST_PKT_CONTROL_WC(word_count) |
  318 + HOST_PKT_CONTROL_VC(0) |
  319 + HOST_PKT_CONTROL_DT(di) |
  320 + HOST_PKT_CONTROL_HS_SEL(mode) |
  321 + HOST_PKT_CONTROL_BTA_TX(need_bta);
  322 +
  323 + debug("pkt_control = %x\n", pkt_control);
  324 + writel(pkt_control, mipi_dsi->mmio_base + HOST_PKT_CONTROL);
  325 +}
  326 +
  327 +static void mipi_dsi_wr_tx_data(struct mipi_dsi_northwest_info *mipi_dsi,
  328 + uint32_t tx_data)
  329 +{
  330 + writel(tx_data, mipi_dsi->mmio_base + HOST_TX_PAYLOAD);
  331 +}
  332 +
  333 +static void mipi_dsi_long_data_wr(struct mipi_dsi_northwest_info *mipi_dsi,
  334 + const uint8_t *data0, uint32_t data_size)
  335 +{
  336 + uint32_t data_cnt = 0, payload = 0;
  337 +
  338 + /* in case that data count is more than 4 */
  339 + for (data_cnt = 0; data_cnt < data_size; data_cnt += 4) {
  340 + /*
  341 + * after sending 4bytes per one time,
  342 + * send remainder data less then 4.
  343 + */
  344 + if ((data_size - data_cnt) < 4) {
  345 + if ((data_size - data_cnt) == 3) {
  346 + payload = data0[data_cnt] |
  347 + (data0[data_cnt + 1] << 8) |
  348 + (data0[data_cnt + 2] << 16);
  349 + debug("count = 3 payload = %x, %x %x %x\n",
  350 + payload, data0[data_cnt], data0[data_cnt + 1], data0[data_cnt + 2]);
  351 + } else if ((data_size - data_cnt) == 2) {
  352 + payload = data0[data_cnt] |
  353 + (data0[data_cnt + 1] << 8);
  354 + debug("count = 2 payload = %x, %x %x\n",
  355 + payload, data0[data_cnt], data0[data_cnt + 1]);
  356 + } else if ((data_size - data_cnt) == 1) {
  357 + payload = data0[data_cnt];
  358 + debug("count = 1 payload = %x, %x\n",
  359 + payload, data0[data_cnt]);
  360 + }
  361 +
  362 + mipi_dsi_wr_tx_data(mipi_dsi, payload);
  363 + } else {
  364 + payload = data0[data_cnt] |
  365 + (data0[data_cnt + 1] << 8) |
  366 + (data0[data_cnt + 2] << 16) |
  367 + (data0[data_cnt + 3] << 24);
  368 +
  369 + debug("count = 4 payload = %x, %x %x %x %x\n",
  370 + payload, *(u8 *)(data0 + data_cnt),
  371 + data0[data_cnt + 1],
  372 + data0[data_cnt + 2],
  373 + data0[data_cnt + 3]);
  374 +
  375 + mipi_dsi_wr_tx_data(mipi_dsi, payload);
  376 + }
  377 + }
  378 +}
  379 +
  380 +static int wait_for_pkt_done(struct mipi_dsi_northwest_info *mipi_dsi, unsigned long timeout)
  381 +{
  382 + uint32_t irq_status;
  383 +
  384 + do {
  385 + irq_status = readl(mipi_dsi->mmio_base + HOST_PKT_STATUS);
  386 + if (irq_status & HOST_IRQ_STATUS_TX_PKT_DONE)
  387 + return timeout;
  388 +
  389 + udelay(1);
  390 + } while (--timeout);
  391 +
  392 + return 0;
  393 +}
  394 +
  395 +static int mipi_dsi_pkt_write(struct mipi_dsi_northwest_info *mipi_dsi,
  396 + u8 data_type, const u32 *buf, int len)
  397 +{
  398 + int ret = 0;
  399 + const uint8_t *data = (const uint8_t *)buf;
  400 +
  401 + debug("mipi_dsi_pkt_write data_type 0x%x, buf 0x%x, len %u\n", data_type, (u32)buf, len);
  402 +
  403 + if (len == 0)
  404 + /* handle generic long write command */
  405 + mipi_dsi_wr_tx_header(mipi_dsi, data_type, data[0], data[1], DSI_LP_MODE, 0);
  406 + else {
  407 + /* handle generic long write command */
  408 + mipi_dsi_long_data_wr(mipi_dsi, data, len);
  409 + mipi_dsi_wr_tx_header(mipi_dsi, data_type, len & 0xff,
  410 + (len & 0xff00) >> 8, DSI_LP_MODE, 0);
  411 + }
  412 +
  413 + /* send packet */
  414 + writel(0x1, mipi_dsi->mmio_base + HOST_SEND_PACKET);
  415 + ret = wait_for_pkt_done(mipi_dsi, MIPI_FIFO_TIMEOUT);
  416 +
  417 + if (!ret) {
  418 + printf("wait tx done timeout!\n");
  419 + return -ETIMEDOUT;
  420 + }
  421 + mdelay(10);
  422 +
  423 + return 0;
  424 +}
  425 +
  426 +static int mipi_dsi_dcs_cmd(struct mipi_dsi_northwest_info *mipi_dsi,
  427 + u8 cmd, const u32 *param, int num)
  428 +{
  429 + int err = 0;
  430 + u32 buf[DSI_CMD_BUF_MAXSIZE];
  431 +
  432 + switch (cmd) {
  433 + case MIPI_DCS_EXIT_SLEEP_MODE:
  434 + case MIPI_DCS_ENTER_SLEEP_MODE:
  435 + case MIPI_DCS_SET_DISPLAY_ON:
  436 + case MIPI_DCS_SET_DISPLAY_OFF:
  437 + buf[0] = cmd;
  438 + buf[1] = 0x0;
  439 + err = mipi_dsi_pkt_write(mipi_dsi,
  440 + MIPI_DSI_DCS_SHORT_WRITE, buf, 0);
  441 + break;
  442 +
  443 + default:
  444 + printf("MIPI DSI DCS Command:0x%x Not supported!\n", cmd);
  445 + break;
  446 + }
  447 +
  448 + return err;
  449 +}
  450 +
  451 +static void mipi_dsi_shutdown(struct mipi_dsi_northwest_info *mipi_dsi)
  452 +{
  453 + mipi_display_enter_sleep(mipi_dsi);
  454 +
  455 + writel(0x1, mipi_dsi->mmio_base + DPHY_PD_PLL);
  456 + writel(0x1, mipi_dsi->mmio_base + DPHY_PD_DPHY);
  457 +
  458 + enable_mipi_dsi_clk(0);
  459 +
  460 + /* Assert resets */
  461 + /* escape domain */
  462 + clrbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_RST_ESC_N);
  463 +
  464 + /* byte domain */
  465 + clrbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_RST_BYTE_N);
  466 +
  467 + /* dpi domain */
  468 + clrbits_le32(mipi_dsi->sim_base + SIM_SOPT1CFG, DSI_RST_DPI_N);
  469 +}
  470 +
  471 +struct mipi_dsi_northwest_info *dsi_info = NULL;
  472 +
  473 +int mipi_dsi_northwest_setup(u32 base_addr, u32 sim_addr)
  474 +{
  475 + if (dsi_info != NULL) {
  476 + printf("mipi_dsi_northwest has been initialized.\n");
  477 + return -EBUSY;
  478 + }
  479 +
  480 + dsi_info = (struct mipi_dsi_northwest_info *)malloc(sizeof(struct mipi_dsi_northwest_info));
  481 + if (!dsi_info) {
  482 + printf("failed to allocate mipi_dsi_northwest_info object.\n");
  483 + return -ENOMEM;
  484 + }
  485 +
  486 + dsi_info->mmio_base = base_addr;
  487 + dsi_info->sim_base = sim_addr;
  488 + dsi_info->mipi_dsi_pkt_write = &mipi_dsi_pkt_write;
  489 + dsi_info->dsi_panel_dev = NULL;
  490 + dsi_info->dsi_panel_drv = NULL;
  491 + dsi_info->enabled = 0;
  492 +
  493 + return 0;
  494 +}
  495 +
  496 +/* Register a LCD panel device */
  497 +int mipi_dsi_northwest_register_panel_device(struct mipi_dsi_northwest_panel_device *panel_dev)
  498 +{
  499 + if (!panel_dev) {
  500 + printf("mipi_dsi_northwest_panel_device is NULL.\n");
  501 + return -EFAULT;
  502 + }
  503 +
  504 + if (!panel_dev->name) {
  505 + printf("mipi_dsi_northwest_panel_device name is NULL.\n");
  506 + return -EFAULT;
  507 + }
  508 +
  509 + if (!dsi_info) {
  510 + printf("mipi_dsi_northwest is not initialized\n");
  511 + return -EFAULT;
  512 + }
  513 +
  514 + if (dsi_info->dsi_panel_drv) {
  515 + if (strcmp(panel_dev->name, dsi_info->dsi_panel_drv->name)) {
  516 + printf("The panel device name %s is not for LCD driver %s\n",
  517 + panel_dev->name, dsi_info->dsi_panel_drv->name);
  518 + return -EFAULT;
  519 + }
  520 + }
  521 +
  522 + dsi_info->dsi_panel_dev = panel_dev;
  523 + panel_dev->host = dsi_info;
  524 +
  525 + return 0;
  526 +}
  527 +
  528 +/* Register a LCD panel driver, will search the panel device to bind with them */
  529 +int mipi_dsi_northwest_register_panel_driver(struct mipi_dsi_northwest_panel_driver *panel_drv)
  530 +{
  531 + if (!panel_drv) {
  532 + printf("mipi_dsi_northwest_panel_driver is NULL.\n");
  533 + return -EFAULT;
  534 + }
  535 +
  536 + if (!panel_drv->name) {
  537 + printf("mipi_dsi_northwest_panel_driver name is NULL.\n");
  538 + return -EFAULT;
  539 + }
  540 +
  541 + if (!dsi_info) {
  542 + printf("mipi_dsi_northwest is not initialized\n");
  543 + return -EFAULT;
  544 + }
  545 +
  546 + if (dsi_info->dsi_panel_dev) {
  547 + if (strcmp(panel_drv->name, dsi_info->dsi_panel_dev->name)) {
  548 + printf("The panel driver name %s is not for LCD device %s\n",
  549 + panel_drv->name, dsi_info->dsi_panel_dev->name);
  550 + return -EFAULT;
  551 + }
  552 + }
  553 +
  554 + dsi_info->dsi_panel_drv = panel_drv;
  555 +
  556 + return 0;
  557 +}
  558 +
  559 +/* Enable the mipi dsi display */
  560 +int mipi_dsi_northwest_enable(void)
  561 +{
  562 + if (!dsi_info->dsi_panel_dev || !dsi_info->dsi_panel_drv)
  563 + return -ENODEV;
  564 +
  565 + mipi_dsi_enable(dsi_info);
  566 +
  567 + dsi_info->enabled = 1;
  568 +
  569 + return 0;
  570 +}
  571 +
  572 +/* Disable and shutdown the mipi dsi display */
  573 +int mipi_dsi_northwest_shutdown(void)
  574 +{
  575 + if (!dsi_info->enabled)
  576 + return 0;
  577 +
  578 + mipi_dsi_shutdown(dsi_info);
  579 + board_mipi_panel_shutdown();
  580 +
  581 + dsi_info->enabled = 0;
  582 +
  583 + return 0;
  584 +}
drivers/video/mipi_dsi_northwest_regs.h
  1 +/*
  2 + * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
  3 + * Copyright 2017 NXP
  4 + *
  5 + * SPDX-License-Identifier: GPL-2.0+
  6 + */
  7 +
  8 +
  9 +#ifndef __MIPI_DSI_NORTHWEST_REGS_H
  10 +#define __MIPI_DSI_NORTHWEST_REGS_H
  11 +
  12 +/* ---------------------------- register offsets --------------------------- */
  13 +
  14 +/* sim */
  15 +#define SIM_SOPT1 0x0
  16 +#define MIPI_ISO_DISABLE 0x8
  17 +
  18 +#define SIM_SOPT1CFG 0x4
  19 +#define DSI_RST_DPI_N 0x80000000
  20 +#define DSI_RST_ESC_N 0x40000000
  21 +#define DSI_RST_BYTE_N 0x20000000
  22 +#define DSI_SD 0x200
  23 +#define DSI_CM 0x100
  24 +#define DSI_PLL_EN 0x80
  25 +
  26 +/* dphy */
  27 +#define DPHY_PD_DPHY 0x300
  28 +#define DPHY_M_PRG_HS_PREPARE 0x304
  29 +#define DPHY_MC_PRG_HS_PREPARE 0x308
  30 +#define DPHY_M_PRG_HS_ZERO 0x30c
  31 +#define DPHY_MC_PRG_HS_ZERO 0x310
  32 +#define DPHY_M_PRG_HS_TRAIL 0x314
  33 +#define DPHY_MC_PRG_HS_TRAIL 0x318
  34 +#define DPHY_PD_PLL 0x31c
  35 +#define DPHY_TST 0x320
  36 +#define DPHY_CN 0x324
  37 +#define DPHY_CM 0x328
  38 +#define DPHY_CO 0x32c
  39 +#define DPHY_LOCK 0x330
  40 +#define DPHY_LOCK_BYP 0x334
  41 +#define DPHY_RTERM_SEL 0x338
  42 +#define DPHY_AUTO_PD_EN 0x33c
  43 +#define DPHY_RXLPRP 0x340
  44 +#define DPHY_RXCDRP 0x344
  45 +
  46 +/* host */
  47 +#define HOST_CFG_NUM_LANES 0x0
  48 +#define HOST_CFG_NONCONTINUOUS_CLK 0x4
  49 +#define HOST_CFG_T_PRE 0x8
  50 +#define HOST_CFG_T_POST 0xc
  51 +#define HOST_CFG_TX_GAP 0x10
  52 +#define HOST_CFG_AUTOINSERT_EOTP 0x14
  53 +#define HOST_CFG_EXTRA_CMDS_AFTER_EOTP 0x18
  54 +#define HOST_CFG_HTX_TO_COUNT 0x1c
  55 +#define HOST_CFG_LRX_H_TO_COUNT 0x20
  56 +#define HOST_CFG_BTA_H_TO_COUNT 0x24
  57 +#define HOST_CFG_TWAKEUP 0x28
  58 +#define HOST_CFG_STATUS_OUT 0x2c
  59 +#define HOST_RX_ERROR_STATUS 0x30
  60 +
  61 +/* dpi */
  62 +#define DPI_PIXEL_PAYLOAD_SIZE 0x200
  63 +#define DPI_PIXEL_FIFO_SEND_LEVEL 0x204
  64 +#define DPI_INTERFACE_COLOR_CODING 0x208
  65 +#define DPI_PIXEL_FORMAT 0x20c
  66 +#define DPI_VSYNC_POLARITY 0x210
  67 +#define DPI_HSYNC_POLARITY 0x214
  68 +#define DPI_VIDEO_MODE 0x218
  69 +#define DPI_HFP 0x21c
  70 +#define DPI_HBP 0x220
  71 +#define DPI_HSA 0x224
  72 +#define DPI_ENABLE_MULT_PKTS 0x228
  73 +#define DPI_VBP 0x22c
  74 +#define DPI_VFP 0x230
  75 +#define DPI_BLLP_MODE 0x234
  76 +#define DPI_USE_NULL_PKT_BLLP 0x238
  77 +#define DPI_VACTIVE 0x23c
  78 +#define DPI_VC 0x240
  79 +
  80 +/* apb pkt */
  81 +#define HOST_TX_PAYLOAD 0x280
  82 +
  83 +#define HOST_PKT_CONTROL 0x284
  84 +#define HOST_PKT_CONTROL_WC(x) (((x) & 0xffff) << 0)
  85 +#define HOST_PKT_CONTROL_VC(x) (((x) & 0x3) << 16)
  86 +#define HOST_PKT_CONTROL_DT(x) (((x) & 0x3f) << 18)
  87 +#define HOST_PKT_CONTROL_HS_SEL(x) (((x) & 0x1) << 24)
  88 +#define HOST_PKT_CONTROL_BTA_TX(x) (((x) & 0x1) << 25)
  89 +#define HOST_PKT_CONTROL_BTA_NO_TX(x) (((x) & 0x1) << 26)
  90 +
  91 +#define HOST_SEND_PACKET 0x288
  92 +#define HOST_PKT_STATUS 0x28c
  93 +#define HOST_PKT_FIFO_WR_LEVEL 0x290
  94 +#define HOST_PKT_FIFO_RD_LEVEL 0x294
  95 +#define HOST_PKT_RX_PAYLOAD 0x298
  96 +
  97 +#define HOST_PKT_RX_PKT_HEADER 0x29c
  98 +#define HOST_PKT_RX_PKT_HEADER_WC(x) (((x) & 0xffff) << 0)
  99 +#define HOST_PKT_RX_PKT_HEADER_DT(x) (((x) & 0x3f) << 16)
  100 +#define HOST_PKT_RX_PKT_HEADER_VC(x) (((x) & 0x3) << 22)
  101 +
  102 +#define HOST_IRQ_STATUS 0x2a0
  103 +#define HOST_IRQ_STATUS_SM_NOT_IDLE (1 << 0)
  104 +#define HOST_IRQ_STATUS_TX_PKT_DONE (1 << 1)
  105 +#define HOST_IRQ_STATUS_DPHY_DIRECTION (1 << 2)
  106 +#define HOST_IRQ_STATUS_TX_FIFO_OVFLW (1 << 3)
  107 +#define HOST_IRQ_STATUS_TX_FIFO_UDFLW (1 << 4)
  108 +#define HOST_IRQ_STATUS_RX_FIFO_OVFLW (1 << 5)
  109 +#define HOST_IRQ_STATUS_RX_FIFO_UDFLW (1 << 6)
  110 +#define HOST_IRQ_STATUS_RX_PKT_HDR_RCVD (1 << 7)
  111 +#define HOST_IRQ_STATUS_RX_PKT_PAYLOAD_DATA_RCVD (1 << 8)
  112 +#define HOST_IRQ_STATUS_HOST_BTA_TIMEOUT (1 << 29)
  113 +#define HOST_IRQ_STATUS_LP_RX_TIMEOUT (1 << 30)
  114 +#define HOST_IRQ_STATUS_HS_TX_TIMEOUT (1 << 31)
  115 +
  116 +#define HOST_IRQ_STATUS2 0x2a4
  117 +#define HOST_IRQ_STATUS2_SINGLE_BIT_ECC_ERR (1 << 0)
  118 +#define HOST_IRQ_STATUS2_MULTI_BIT_ECC_ERR (1 << 1)
  119 +#define HOST_IRQ_STATUS2_CRC_ERR (1 << 2)
  120 +
  121 +#define HOST_IRQ_MASK 0x2a8
  122 +#define HOST_IRQ_MASK_SM_NOT_IDLE_MASK (1 << 0)
  123 +#define HOST_IRQ_MASK_TX_PKT_DONE_MASK (1 << 1)
  124 +#define HOST_IRQ_MASK_DPHY_DIRECTION_MASK (1 << 2)
  125 +#define HOST_IRQ_MASK_TX_FIFO_OVFLW_MASK (1 << 3)
  126 +#define HOST_IRQ_MASK_TX_FIFO_UDFLW_MASK (1 << 4)
  127 +#define HOST_IRQ_MASK_RX_FIFO_OVFLW_MASK (1 << 5)
  128 +#define HOST_IRQ_MASK_RX_FIFO_UDFLW_MASK (1 << 6)
  129 +#define HOST_IRQ_MASK_RX_PKT_HDR_RCVD_MASK (1 << 7)
  130 +#define HOST_IRQ_MASK_RX_PKT_PAYLOAD_DATA_RCVD_MASK (1 << 8)
  131 +#define HOST_IRQ_MASK_HOST_BTA_TIMEOUT_MASK (1 << 29)
  132 +#define HOST_IRQ_MASK_LP_RX_TIMEOUT_MASK (1 << 30)
  133 +#define HOST_IRQ_MASK_HS_TX_TIMEOUT_MASK (1 << 31)
  134 +
  135 +#define HOST_IRQ_MASK2 0x2ac
  136 +#define HOST_IRQ_MASK2_SINGLE_BIT_ECC_ERR_MASK (1 << 0)
  137 +#define HOST_IRQ_MASK2_MULTI_BIT_ECC_ERR_MASK (1 << 1)
  138 +#define HOST_IRQ_MASK2_CRC_ERR_MASK (1 << 2)
  139 +
  140 +/* ------------------------------------- end -------------------------------- */
  141 +
  142 +#endif
include/mipi_dsi_northwest.h
  1 +/*
  2 + * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
  3 + * Copyright 2017 NXP
  4 + *
  5 + * SPDX-License-Identifier: GPL-2.0+
  6 + */
  7 +
  8 +
  9 +#ifndef __MIPI_DSI_NORTHWEST_H
  10 +#define __MIPI_DSI_NORTHWEST_H
  11 +
  12 +#include <linux/fb.h>
  13 +
  14 +#define DSI_CMD_BUF_MAXSIZE (128)
  15 +
  16 +/*
  17 + * device structure for mipi-dsi based lcd panel.
  18 + *
  19 + * @name: name of the device to use with this device,
  20 + * the name will be used for binding driver.
  21 + * @mode: video mode parameters for the panel.
  22 + * @bpp: bits per pixel. only 24 bits is supported.
  23 + * @virtual_ch_id: virtual channel id for this dsi device.
  24 + * @data_lane_num: the data lane number, max is 2.
  25 + * @host: pointer to the host driver instance, will be setup
  26 + * during register device.
  27 + */
  28 +struct mipi_dsi_northwest_panel_device {
  29 + const char *name;
  30 + struct fb_videomode mode;
  31 + int bpp;
  32 + u32 virtual_ch_id;
  33 + u32 data_lane_num;
  34 +
  35 + struct mipi_dsi_northwest_info *host;
  36 +};
  37 +
  38 +
  39 +/*
  40 + * driver structure for mipi-dsi based lcd panel.
  41 + *
  42 + * this structure should be registered by lcd panel driver.
  43 + * mipi-dsi driver seeks lcd panel registered through name field
  44 + * and calls these callback functions in appropriate time.
  45 + *
  46 + * @name: name of the driver to use with this device, or an
  47 + * alias for that name.
  48 + * @mipi_panel_setup: callback pointer for initializing lcd panel based on mipi
  49 + * dsi interface.
  50 + */
  51 +struct mipi_dsi_northwest_panel_driver {
  52 + const char *name;
  53 +
  54 + int (*mipi_panel_setup)(struct mipi_dsi_northwest_panel_device *panel_dev);
  55 +};
  56 +
  57 +/*
  58 + * mipi-dsi northwest driver information structure, holds useful data for the driver.
  59 + */
  60 +struct mipi_dsi_northwest_info {
  61 + u32 mmio_base;
  62 + u32 sim_base;
  63 + int enabled;
  64 + struct mipi_dsi_northwest_panel_device *dsi_panel_dev;
  65 + struct mipi_dsi_northwest_panel_driver *dsi_panel_drv;
  66 +
  67 + int (*mipi_dsi_pkt_write)(struct mipi_dsi_northwest_info *mipi_dsi,
  68 + u8 data_type, const u32 *buf, int len);
  69 +};
  70 +
  71 +/* Setup mipi dsi host driver instance, with base address and SIM address provided */
  72 +int mipi_dsi_northwest_setup(u32 base_addr, u32 sim_addr);
  73 +
  74 +/* Create a LCD panel device, will search the panel driver to bind with them */
  75 +int mipi_dsi_northwest_register_panel_device(struct mipi_dsi_northwest_panel_device *panel_dev);
  76 +
  77 +/* Register a LCD panel driver, will search the panel device to bind with them */
  78 +int mipi_dsi_northwest_register_panel_driver(struct mipi_dsi_northwest_panel_driver *panel_drv);
  79 +
  80 +/* Enable the mipi dsi display */
  81 +int mipi_dsi_northwest_enable(void);
  82 +
  83 +/* Disable and shutdown the mipi dsi display */
  84 +int mipi_dsi_northwest_shutdown(void);
  85 +
  86 +void hx8363_init(void);
  87 +
  88 +#endif
scripts/config_whitelist.txt
... ... @@ -1387,6 +1387,7 @@
1387 1387 CONFIG_MXC_KPD_COLMAX
1388 1388 CONFIG_MXC_KPD_ROWMAX
1389 1389 CONFIG_MXC_MCI_REGS_BASE
  1390 +CONFIG_MXC_MIPI_DSI_NORTHWEST
1390 1391 CONFIG_MXC_NAND_HWECC
1391 1392 CONFIG_MXC_NAND_IP_REGS_BASE
1392 1393 CONFIG_MXC_NAND_REGS_BASE