video: fbdev: mxc: add Samsung MIPI DSI driver support
Add the framebuffer driver support for the Samsung MIPI DSI controller. Signed-off-by: Fancy Fang <chen.fang@nxp.com>5.4-rM2-2.2.x-imx-squashed
parent
dd204551ec
commit
baae63d78c
|
@ -61,3 +61,7 @@ config FB_MXC_RK_PANEL_RK055IQH042
|
|||
tristate "ROCKTECH Panel RK055IQH042"
|
||||
depends on FB_MXC_DISP_FRAMEWORK
|
||||
depends on FB_MXC_MIPI_DSI_NORTHWEST
|
||||
|
||||
config FB_MXC_MIPI_DSI_SAMSUNG
|
||||
tristate "MXC MIPI_DSI_SAMSUNG"
|
||||
depends on FB_MXS
|
||||
|
|
|
@ -5,3 +5,4 @@ obj-$(CONFIG_FB_MXC_ADV7535) += adv7535.o
|
|||
obj-$(CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E) += mxcfb_hx8363_wvga.o
|
||||
obj-$(CONFIG_FB_MXC_RK_PANEL_RK055AHD042) += mxcfb_rm68200_wxga.o
|
||||
obj-$(CONFIG_FB_MXC_RK_PANEL_RK055IQH042) += mxcfb_rm68191_qhd.o
|
||||
obj-$(CONFIG_FB_MXC_MIPI_DSI_SAMSUNG) += mipi_dsi_samsung.o
|
||||
|
|
|
@ -0,0 +1,952 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/mipi_dsi_samsung.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mxcfb.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/busfreq-imx.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/delay.h>
|
||||
#include <video/mipi_display.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
|
||||
#include "mipi_dsi.h"
|
||||
|
||||
#define DISPDRV_MIPI "mipi_dsi_samsung"
|
||||
#define ROUND_UP(x) ((x)+1)
|
||||
#define NS2PS_RATIO (1000)
|
||||
#define MIPI_LCD_SLEEP_MODE_DELAY (120)
|
||||
#define MIPI_FIFO_TIMEOUT msecs_to_jiffies(250)
|
||||
|
||||
static struct mipi_dsi_match_lcd mipi_dsi_lcd_db[] = {
|
||||
#ifdef CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL
|
||||
{
|
||||
"TRULY-WVGA",
|
||||
{mipid_hx8369_get_lcd_videomode, mipid_hx8369_lcd_setup}
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_FB_MXC_TRULY_PANEL_TFT3P5079E
|
||||
{
|
||||
"TRULY-WVGA-TFT3P5079E",
|
||||
{mipid_otm8018b_get_lcd_videomode, mipid_otm8018b_lcd_setup}
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E
|
||||
{
|
||||
"TRULY-WVGA-TFT3P5581E",
|
||||
{mipid_hx8363_get_lcd_videomode, mipid_hx8363_lcd_setup}
|
||||
},
|
||||
#endif
|
||||
{
|
||||
"", {NULL, NULL}
|
||||
}
|
||||
};
|
||||
|
||||
enum mipi_dsi_mode {
|
||||
DSI_COMMAND_MODE,
|
||||
DSI_VIDEO_MODE
|
||||
};
|
||||
|
||||
enum mipi_dsi_trans_mode {
|
||||
DSI_LP_MODE,
|
||||
DSI_HS_MODE
|
||||
};
|
||||
|
||||
static struct regulator *mipi_phy_reg;
|
||||
static DECLARE_COMPLETION(dsi_rx_done);
|
||||
static DECLARE_COMPLETION(dsi_tx_done);
|
||||
|
||||
static void mipi_dsi_dphy_power_down(void);
|
||||
static void mipi_dsi_set_mode(struct mipi_dsi_info *mipi_dsi,
|
||||
enum mipi_dsi_trans_mode mode);
|
||||
|
||||
static int mipi_dsi_lcd_init(struct mipi_dsi_info *mipi_dsi,
|
||||
struct mxc_dispdrv_setting *setting)
|
||||
{
|
||||
int i, size, err;
|
||||
struct fb_videomode *mipi_lcd_modedb;
|
||||
struct fb_videomode mode;
|
||||
struct device *dev = &mipi_dsi->pdev->dev;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mipi_dsi_lcd_db); i++) {
|
||||
if (!strcmp(mipi_dsi->lcd_panel,
|
||||
mipi_dsi_lcd_db[i].lcd_panel)) {
|
||||
mipi_dsi->lcd_callback =
|
||||
&mipi_dsi_lcd_db[i].lcd_callback;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(mipi_dsi_lcd_db)) {
|
||||
dev_err(dev, "failed to find supported lcd panel.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* set default bpp to 32 if not set*/
|
||||
if (!setting->default_bpp)
|
||||
setting->default_bpp = 32;
|
||||
|
||||
mipi_dsi->lcd_callback->get_mipi_lcd_videomode(&mipi_lcd_modedb, &size,
|
||||
&mipi_dsi->lcd_config);
|
||||
|
||||
err = fb_find_mode(&setting->fbi->var, setting->fbi,
|
||||
setting->dft_mode_str,
|
||||
mipi_lcd_modedb, size, NULL,
|
||||
setting->default_bpp);
|
||||
if (err != 1)
|
||||
fb_videomode_to_var(&setting->fbi->var, mipi_lcd_modedb);
|
||||
|
||||
INIT_LIST_HEAD(&setting->fbi->modelist);
|
||||
for (i = 0; i < size; i++) {
|
||||
fb_var_to_videomode(&mode, &setting->fbi->var);
|
||||
if (fb_mode_is_equal(&mode, mipi_lcd_modedb + i)) {
|
||||
err = fb_add_videomode(mipi_lcd_modedb + i,
|
||||
&setting->fbi->modelist);
|
||||
mipi_dsi->mode = mipi_lcd_modedb + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((err < 0) || (size == i)) {
|
||||
dev_err(dev, "failed to add videomode.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mipi_dsi_wr_tx_header(struct mipi_dsi_info *mipi_dsi,
|
||||
u8 di, u8 data0, u8 data1)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
reg = (data1 << 16) | (data0 << 8) | ((di & 0x3f) << 0);
|
||||
|
||||
writel(reg, mipi_dsi->mmio_base + MIPI_DSI_PKTHDR);
|
||||
}
|
||||
|
||||
static void mipi_dsi_wr_tx_data(struct mipi_dsi_info *mipi_dsi,
|
||||
unsigned int tx_data)
|
||||
{
|
||||
writel(tx_data, mipi_dsi->mmio_base + MIPI_DSI_PAYLOAD);
|
||||
}
|
||||
|
||||
static void mipi_dsi_long_data_wr(struct mipi_dsi_info *mipi_dsi,
|
||||
const unsigned char *data0, unsigned int data_size)
|
||||
{
|
||||
unsigned int data_cnt = 0, payload = 0;
|
||||
|
||||
/* in case that data count is more then 4 */
|
||||
for (data_cnt = 0; data_cnt < data_size; data_cnt += 4) {
|
||||
/*
|
||||
* after sending 4bytes per one time,
|
||||
* send remainder data less then 4.
|
||||
*/
|
||||
if ((data_size - data_cnt) < 4) {
|
||||
if ((data_size - data_cnt) == 3) {
|
||||
payload = data0[data_cnt] |
|
||||
data0[data_cnt + 1] << 8 |
|
||||
data0[data_cnt + 2] << 16;
|
||||
dev_dbg(&mipi_dsi->pdev->dev, "count = 3 payload = %x, %x %x %x\n",
|
||||
payload, data0[data_cnt],
|
||||
data0[data_cnt + 1],
|
||||
data0[data_cnt + 2]);
|
||||
} else if ((data_size - data_cnt) == 2) {
|
||||
payload = data0[data_cnt] |
|
||||
data0[data_cnt + 1] << 8;
|
||||
dev_dbg(&mipi_dsi->pdev->dev,
|
||||
"count = 2 payload = %x, %x %x\n", payload,
|
||||
data0[data_cnt],
|
||||
data0[data_cnt + 1]);
|
||||
} else if ((data_size - data_cnt) == 1) {
|
||||
payload = data0[data_cnt];
|
||||
}
|
||||
|
||||
mipi_dsi_wr_tx_data(mipi_dsi, payload);
|
||||
/* send 4bytes per one time. */
|
||||
} else {
|
||||
payload = data0[data_cnt] |
|
||||
data0[data_cnt + 1] << 8 |
|
||||
data0[data_cnt + 2] << 16 |
|
||||
data0[data_cnt + 3] << 24;
|
||||
|
||||
dev_dbg(&mipi_dsi->pdev->dev,
|
||||
"count = 4 payload = %x, %x %x %x %x\n",
|
||||
payload, *(u8 *)(data0 + data_cnt),
|
||||
data0[data_cnt + 1],
|
||||
data0[data_cnt + 2],
|
||||
data0[data_cnt + 3]);
|
||||
|
||||
mipi_dsi_wr_tx_data(mipi_dsi, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int mipi_dsi_pkt_write(struct mipi_dsi_info *mipi_dsi,
|
||||
u8 data_type, const u32 *buf, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
struct platform_device *pdev = mipi_dsi->pdev;
|
||||
const unsigned char *data = (const unsigned char*)buf;
|
||||
|
||||
if (len == 0)
|
||||
/* handle generic short write command */
|
||||
mipi_dsi_wr_tx_header(mipi_dsi, data_type, data[0], data[1]);
|
||||
else {
|
||||
reinit_completion(&dsi_tx_done);
|
||||
|
||||
/* handle generic long write command */
|
||||
mipi_dsi_long_data_wr(mipi_dsi, data, len);
|
||||
mipi_dsi_wr_tx_header(mipi_dsi, data_type, len & 0xff, (len & 0xff00) >> 8);
|
||||
|
||||
ret = wait_for_completion_timeout(&dsi_tx_done, MIPI_FIFO_TIMEOUT);
|
||||
if (!ret) {
|
||||
dev_err(&pdev->dev, "wait tx done timeout!\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
mdelay(10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mipi_dsi_rd_tx_header(struct mipi_dsi_info *mipi_dsi,
|
||||
u8 data_type, u8 data0)
|
||||
{
|
||||
unsigned int reg = (data_type << 0) | (data0 << 8);
|
||||
|
||||
writel(reg, mipi_dsi->mmio_base + MIPI_DSI_PKTHDR);
|
||||
}
|
||||
|
||||
static unsigned int mipi_dsi_rd_rx_fifo(struct mipi_dsi_info *mipi_dsi)
|
||||
{
|
||||
return readl(mipi_dsi->mmio_base + MIPI_DSI_RXFIFO);
|
||||
}
|
||||
|
||||
static int mipi_dsi_pkt_read(struct mipi_dsi_info *mipi_dsi,
|
||||
u8 data_type, u32 *buf, int len)
|
||||
{
|
||||
int ret;
|
||||
struct platform_device *pdev = mipi_dsi->pdev;
|
||||
|
||||
if (len <= 4) {
|
||||
reinit_completion(&dsi_rx_done);
|
||||
|
||||
mipi_dsi_rd_tx_header(mipi_dsi, data_type, buf[0]);
|
||||
|
||||
ret = wait_for_completion_timeout(&dsi_rx_done, MIPI_FIFO_TIMEOUT);
|
||||
if (!ret) {
|
||||
dev_err(&pdev->dev, "wait rx done timeout!\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
buf[0] = mipi_dsi_rd_rx_fifo(mipi_dsi);
|
||||
buf[0] = buf[0] >> 8;
|
||||
}
|
||||
else {
|
||||
/* TODO: add support later */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mipi_dsi_dcs_cmd(struct mipi_dsi_info *mipi_dsi,
|
||||
u8 cmd, const u32 *param, int num)
|
||||
{
|
||||
int err = 0;
|
||||
u32 buf[DSI_CMD_BUF_MAXSIZE];
|
||||
|
||||
switch (cmd) {
|
||||
case MIPI_DCS_EXIT_SLEEP_MODE:
|
||||
case MIPI_DCS_ENTER_SLEEP_MODE:
|
||||
case MIPI_DCS_SET_DISPLAY_ON:
|
||||
case MIPI_DCS_SET_DISPLAY_OFF:
|
||||
buf[0] = cmd;
|
||||
err = mipi_dsi_pkt_write(mipi_dsi,
|
||||
MIPI_DSI_DCS_SHORT_WRITE, buf, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(&mipi_dsi->pdev->dev,
|
||||
"MIPI DSI DCS Command:0x%x Not supported!\n", cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mipi_dsi_set_main_standby(struct mipi_dsi_info *mipi_dsi,
|
||||
unsigned int enable)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
reg = readl(mipi_dsi->mmio_base + MIPI_DSI_MDRESOL);
|
||||
|
||||
reg &= ~MIPI_DSI_MAIN_STANDBY(1);
|
||||
|
||||
if (enable)
|
||||
reg |= MIPI_DSI_MAIN_STANDBY(1);
|
||||
|
||||
writel(reg, mipi_dsi->mmio_base + MIPI_DSI_MDRESOL);
|
||||
}
|
||||
|
||||
static void mipi_dsi_power_off(struct mxc_dispdrv_handle *disp)
|
||||
{
|
||||
int err;
|
||||
struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
|
||||
|
||||
err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_ENTER_SLEEP_MODE,
|
||||
NULL, 0);
|
||||
if (err) {
|
||||
dev_err(&mipi_dsi->pdev->dev,
|
||||
"MIPI DSI DCS Command display on error!\n");
|
||||
}
|
||||
msleep(MIPI_LCD_SLEEP_MODE_DELAY);
|
||||
|
||||
mipi_dsi_set_main_standby(mipi_dsi, 0);
|
||||
|
||||
clk_disable_unprepare(mipi_dsi->dphy_clk);
|
||||
clk_disable_unprepare(mipi_dsi->cfg_clk);
|
||||
}
|
||||
|
||||
static void mipi_dsi_dphy_power_on(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
regulator_set_voltage(mipi_phy_reg, 1000000, 1000000);
|
||||
|
||||
ret = regulator_enable(mipi_phy_reg);
|
||||
if (ret){
|
||||
dev_err(&pdev->dev, "failed to enable mipi phy regulatore\n");
|
||||
BUG_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void mipi_dsi_dphy_power_down(void)
|
||||
{
|
||||
regulator_disable(mipi_phy_reg);
|
||||
}
|
||||
|
||||
static int mipi_dsi_lane_stop_state(struct mipi_dsi_info *mipi_dsi)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
reg = readl(mipi_dsi->mmio_base + MIPI_DSI_STATUS);
|
||||
|
||||
if (((reg & MIPI_DSI_STOP_STATE_DAT(0x3)) == 0x3) &&
|
||||
((reg & MIPI_DSI_STOP_STATE_CLK(0x1)) ||
|
||||
(reg & MIPI_DSI_TX_READY_HS_CLK(0x1))))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mipi_dsi_init_interrupt(struct mipi_dsi_info *mipi_dsi)
|
||||
{
|
||||
unsigned int intsrc, intmsk;
|
||||
|
||||
intsrc = (INTSRC_SFR_PL_FIFO_EMPTY | INTSRC_RX_DATA_DONE);
|
||||
writel(intsrc, mipi_dsi->mmio_base + MIPI_DSI_INTSRC);
|
||||
|
||||
intmsk = ~(INTMSK_SFR_PL_FIFO_EMPTY | INTMSK_RX_DATA_DONE);
|
||||
writel(intmsk, mipi_dsi->mmio_base + MIPI_DSI_INTMSK);
|
||||
}
|
||||
|
||||
static int mipi_dsi_master_init(struct mipi_dsi_info *mipi_dsi,
|
||||
bool init)
|
||||
{
|
||||
unsigned int time_out = 100;
|
||||
unsigned int reg, byte_clk, esc_div;
|
||||
struct fb_videomode *mode = mipi_dsi->mode;
|
||||
struct device *dev = &mipi_dsi->pdev->dev;
|
||||
|
||||
/* configure DPHY PLL clock */
|
||||
writel(MIPI_DSI_TX_REQUEST_HSCLK(0) |
|
||||
MIPI_DSI_DPHY_SEL(0) |
|
||||
MIPI_DSI_PLL_BYPASS(0) |
|
||||
MIPI_DSI_BYTE_CLK_SRC(0),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_CLKCTRL);
|
||||
if (!strcmp(mipi_dsi->lcd_panel, "TRULY-WVGA-TFT3P5581E"))
|
||||
writel(MIPI_DSI_PLL_EN(1) | MIPI_DSI_PMS(0x3141),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_PLLCTRL);
|
||||
else
|
||||
writel(MIPI_DSI_PLL_EN(1) | MIPI_DSI_PMS(0x4190),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_PLLCTRL);
|
||||
|
||||
/* set PLLTMR: stable time */
|
||||
writel(33024, mipi_dsi->mmio_base + MIPI_DSI_PLLTMR);
|
||||
udelay(300);
|
||||
|
||||
/* configure byte clock */
|
||||
reg = readl(mipi_dsi->mmio_base + MIPI_DSI_CLKCTRL);
|
||||
reg |= MIPI_DSI_BYTE_CLK_EN(1);
|
||||
byte_clk = 1500000000 / 8;
|
||||
esc_div = DIV_ROUND_UP(byte_clk, 20 * 1000000);
|
||||
reg |= (esc_div & 0xffff);
|
||||
/* enable escape clock for clock lane and data lane0 and lane1 */
|
||||
reg |= MIPI_DSI_LANE_ESC_CLK_EN(0x7);
|
||||
reg |= MIPI_DSI_ESC_CLK_EN(1);
|
||||
writel(reg, mipi_dsi->mmio_base + MIPI_DSI_CLKCTRL);
|
||||
|
||||
/* set main display resolution */
|
||||
writel(MIPI_DSI_MAIN_HRESOL(mode->xres) |
|
||||
MIPI_DSI_MAIN_VRESOL(mode->yres) |
|
||||
MIPI_DSI_MAIN_STANDBY(0),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_MDRESOL);
|
||||
|
||||
/* set config register */
|
||||
writel(MIPI_DSI_MFLUSH_VS(1) |
|
||||
MIPI_DSI_SYNC_IN_FORM(0) |
|
||||
MIPI_DSI_BURST_MODE(1) |
|
||||
MIPI_DSI_VIDEO_MODE(1) |
|
||||
MIPI_DSI_AUTO_MODE(0) |
|
||||
MIPI_DSI_HSE_DISABLE_MODE(0) |
|
||||
MIPI_DSI_HFP_DISABLE_MODE(0) |
|
||||
MIPI_DSI_HBP_DISABLE_MODE(0) |
|
||||
MIPI_DSI_HSA_DISABLE_MODE(0) |
|
||||
MIPI_DSI_MAIN_VC(0) |
|
||||
MIPI_DSI_SUB_VC(1) |
|
||||
MIPI_DSI_MAIN_PIX_FORMAT(0x7) |
|
||||
MIPI_DSI_SUB_PIX_FORMAT(0x7) |
|
||||
MIPI_DSI_NUM_OF_DATALANE(0x1) |
|
||||
MIPI_DSI_LANE_EN(0x7), /* enable data lane 0 and 1 */
|
||||
mipi_dsi->mmio_base + MIPI_DSI_CONFIG);
|
||||
|
||||
/* set main display vporch */
|
||||
writel(MIPI_DSI_CMDALLOW(0xf) |
|
||||
MIPI_DSI_STABLE_VFP(mode->lower_margin) |
|
||||
MIPI_DSI_MAIN_VBP(mode->upper_margin),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_MVPORCH);
|
||||
/* set main display hporch */
|
||||
writel(MIPI_DSI_MAIN_HFP(mode->right_margin) |
|
||||
MIPI_DSI_MAIN_HBP(mode->left_margin),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_MHPORCH);
|
||||
/* set main display sync */
|
||||
writel(MIPI_DSI_MAIN_VSA(mode->vsync_len) |
|
||||
MIPI_DSI_MAIN_HSA(mode->hsync_len),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_MSYNC);
|
||||
|
||||
/* configure d-phy timings */
|
||||
if (!strcmp(mipi_dsi->lcd_panel, "TRULY-WVGA-TFT3P5581E")) {
|
||||
writel(MIPI_DSI_M_TLPXCTL(2) | MIPI_DSI_M_THSEXITCTL(4),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING);
|
||||
writel(MIPI_DSI_M_TCLKPRPRCTL(5) |
|
||||
MIPI_DSI_M_TCLKZEROCTL(14) |
|
||||
MIPI_DSI_M_TCLKPOSTCTL(8) |
|
||||
MIPI_DSI_M_TCLKTRAILCTL(3),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING1);
|
||||
writel(MIPI_DSI_M_THSPRPRCTL(3) |
|
||||
MIPI_DSI_M_THSZEROCTL(3) |
|
||||
MIPI_DSI_M_THSTRAILCTL(3),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING2);
|
||||
} else {
|
||||
writel(MIPI_DSI_M_TLPXCTL(11) | MIPI_DSI_M_THSEXITCTL(18),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING);
|
||||
writel(MIPI_DSI_M_TCLKPRPRCTL(13) |
|
||||
MIPI_DSI_M_TCLKZEROCTL(65) |
|
||||
MIPI_DSI_M_TCLKPOSTCTL(17) |
|
||||
MIPI_DSI_M_TCLKTRAILCTL(13),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING1);
|
||||
writel(MIPI_DSI_M_THSPRPRCTL(16) |
|
||||
MIPI_DSI_M_THSZEROCTL(24) |
|
||||
MIPI_DSI_M_THSTRAILCTL(16),
|
||||
mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING2);
|
||||
}
|
||||
|
||||
writel(0xf000f, mipi_dsi->mmio_base + MIPI_DSI_TIMEOUT);
|
||||
|
||||
/* Init FIFO */
|
||||
writel(0x0, mipi_dsi->mmio_base + MIPI_DSI_FIFOCTRL);
|
||||
udelay(300);
|
||||
writel(0x1f, mipi_dsi->mmio_base + MIPI_DSI_FIFOCTRL);
|
||||
|
||||
/* check clock and data lanes are in stop state
|
||||
* which means dphy is in low power mode
|
||||
*/
|
||||
while (!mipi_dsi_lane_stop_state(mipi_dsi)) {
|
||||
time_out--;
|
||||
if (time_out == 0) {
|
||||
dev_err(dev, "MIPI DSI is not stop state.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* transfer commands always in lp mode */
|
||||
writel(MIPI_DSI_CMD_LPDT, mipi_dsi->mmio_base + MIPI_DSI_ESCMODE);
|
||||
|
||||
mipi_dsi_init_interrupt(mipi_dsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mipi_dsi_disp_init(struct mxc_dispdrv_handle *disp,
|
||||
struct mxc_dispdrv_setting *setting)
|
||||
{
|
||||
struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
|
||||
struct device *dev = &mipi_dsi->pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct reset_control *reset = NULL;
|
||||
int ret = 0;
|
||||
|
||||
reset = of_reset_control_get(np, NULL);
|
||||
if (IS_ERR(reset))
|
||||
return PTR_ERR(reset);
|
||||
|
||||
ret = mipi_dsi_lcd_init(mipi_dsi, setting);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to init mipi dsi lcd\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_info(dev, "MIPI DSI dispdrv inited!\n");
|
||||
|
||||
out:
|
||||
reset_control_put(reset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mipi_dsi_disp_deinit(struct mxc_dispdrv_handle *disp)
|
||||
{
|
||||
struct mipi_dsi_info *mipi_dsi;
|
||||
|
||||
mipi_dsi = mxc_dispdrv_getdata(disp);
|
||||
|
||||
mipi_dsi_power_off(mipi_dsi->disp_mipi);
|
||||
if (mipi_dsi->bl)
|
||||
backlight_device_unregister(mipi_dsi->bl);
|
||||
}
|
||||
|
||||
static void mipi_dsi_set_mode(struct mipi_dsi_info *mipi_dsi,
|
||||
enum mipi_dsi_trans_mode mode)
|
||||
{
|
||||
unsigned int dsi_clkctrl;
|
||||
|
||||
dsi_clkctrl = readl(mipi_dsi->mmio_base + MIPI_DSI_CLKCTRL);
|
||||
|
||||
switch (mode) {
|
||||
case DSI_LP_MODE:
|
||||
dsi_clkctrl &= ~MIPI_DSI_TX_REQUEST_HSCLK(1);
|
||||
break;
|
||||
case DSI_HS_MODE:
|
||||
dsi_clkctrl |= MIPI_DSI_TX_REQUEST_HSCLK(1);
|
||||
break;
|
||||
default:
|
||||
dev_err(&mipi_dsi->pdev->dev,
|
||||
"invalid dsi mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
writel(dsi_clkctrl, mipi_dsi->mmio_base + MIPI_DSI_CLKCTRL);
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
static int mipi_dsi_enable(struct mxc_dispdrv_handle *disp,
|
||||
struct fb_info *fbi)
|
||||
{
|
||||
int ret;
|
||||
struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
|
||||
|
||||
if (fbi->state == FBINFO_STATE_SUSPENDED) {
|
||||
if (mipi_dsi->disp_power_on) {
|
||||
ret = regulator_enable(mipi_dsi->disp_power_on);
|
||||
if (ret) {
|
||||
dev_err(&mipi_dsi->pdev->dev, "failed to enable display "
|
||||
"power regulator, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mipi_dsi->dsi_power_on)
|
||||
pm_runtime_get_sync(&mipi_dsi->pdev->dev);
|
||||
|
||||
ret = clk_prepare_enable(mipi_dsi->dphy_clk);
|
||||
ret |= clk_prepare_enable(mipi_dsi->cfg_clk);
|
||||
if (ret) {
|
||||
dev_err(&mipi_dsi->pdev->dev,
|
||||
"clk enable error:%d!\n", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!mipi_dsi->lcd_inited) {
|
||||
ret = mipi_dsi_master_init(mipi_dsi, true);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
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(120);
|
||||
|
||||
/* the panel should be config under LP mode */
|
||||
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->lcd_inited = 1;
|
||||
|
||||
/* change to HS mode for panel display */
|
||||
mipi_dsi_set_mode(mipi_dsi, DSI_HS_MODE);
|
||||
} else {
|
||||
ret = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_EXIT_SLEEP_MODE,
|
||||
NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(&mipi_dsi->pdev->dev,
|
||||
"MIPI DSI DCS Command sleep-in error!\n");
|
||||
}
|
||||
msleep(MIPI_LCD_SLEEP_MODE_DELAY);
|
||||
}
|
||||
|
||||
mipi_dsi_set_main_standby(mipi_dsi, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mipi_dsi_disable(struct mxc_dispdrv_handle *disp,
|
||||
struct fb_info *fbi)
|
||||
{
|
||||
struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
|
||||
|
||||
mipi_dsi_power_off(mipi_dsi->disp_mipi);
|
||||
|
||||
if (fbi->state == FBINFO_STATE_SUSPENDED) {
|
||||
if (mipi_dsi->dsi_power_on) {
|
||||
pm_runtime_put_noidle(&mipi_dsi->pdev->dev);
|
||||
pm_runtime_put_sync_suspend(&mipi_dsi->pdev->dev);
|
||||
pm_runtime_get_noresume(&mipi_dsi->pdev->dev);
|
||||
}
|
||||
|
||||
if (mipi_dsi->disp_power_on)
|
||||
regulator_disable(mipi_dsi->disp_power_on);
|
||||
|
||||
mipi_dsi->lcd_inited = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int mipi_dsi_setup(struct mxc_dispdrv_handle *disp,
|
||||
struct fb_info *fbi)
|
||||
{
|
||||
struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
|
||||
int xres_virtual = fbi->var.xres_virtual;
|
||||
int yres_virtual = fbi->var.yres_virtual;
|
||||
int xoffset = fbi->var.xoffset;
|
||||
int yoffset = fbi->var.yoffset;
|
||||
int pixclock = fbi->var.pixclock;
|
||||
|
||||
if (!mipi_dsi->mode)
|
||||
return 0;
|
||||
|
||||
/* set the mode back to var in case userspace changes it */
|
||||
fb_videomode_to_var(&fbi->var, mipi_dsi->mode);
|
||||
|
||||
/* restore some var entries cached */
|
||||
fbi->var.xres_virtual = xres_virtual;
|
||||
fbi->var.yres_virtual = yres_virtual;
|
||||
fbi->var.xoffset = xoffset;
|
||||
fbi->var.yoffset = yoffset;
|
||||
fbi->var.pixclock = pixclock;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mxc_dispdrv_driver mipi_dsi_drv = {
|
||||
.name = DISPDRV_MIPI,
|
||||
.init = mipi_dsi_disp_init,
|
||||
.deinit = mipi_dsi_disp_deinit,
|
||||
.enable = mipi_dsi_enable,
|
||||
.disable = mipi_dsi_disable,
|
||||
.setup = mipi_dsi_setup,
|
||||
};
|
||||
|
||||
static const struct of_device_id imx_mipi_dsi_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx7d-mipi-dsi", .data = NULL, },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx_mipi_dsi_dt_ids);
|
||||
|
||||
static irqreturn_t mipi_dsi_irq_handler(int irq, void *data)
|
||||
{
|
||||
unsigned int intsrc, intclr;
|
||||
struct mipi_dsi_info *mipi_dsi = data;
|
||||
struct platform_device *pdev = mipi_dsi->pdev;
|
||||
|
||||
intclr = 0;
|
||||
intsrc = readl(mipi_dsi->mmio_base + MIPI_DSI_INTSRC);
|
||||
|
||||
dev_dbg(&pdev->dev, "intsrc = 0x%x\n", intsrc);
|
||||
|
||||
if (intsrc & INTSRC_SFR_PL_FIFO_EMPTY) {
|
||||
dev_dbg(&pdev->dev, "playload tx finished\n");
|
||||
intclr |= INTSRC_SFR_PL_FIFO_EMPTY;
|
||||
complete(&dsi_tx_done);
|
||||
}
|
||||
|
||||
if(intsrc & INTSRC_RX_DATA_DONE) {
|
||||
dev_dbg(&pdev->dev, "rx data finished\n");
|
||||
intclr |= INTSRC_RX_DATA_DONE;
|
||||
complete(&dsi_rx_done);
|
||||
}
|
||||
|
||||
/* clear the interrupts */
|
||||
if (intclr)
|
||||
writel(intclr, mipi_dsi->mmio_base + MIPI_DSI_INTSRC);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called by the driver framework to initialize the MIPI DSI
|
||||
* device.
|
||||
*
|
||||
* @param pdev The device structure for the MIPI DSI passed in by the
|
||||
* driver framework.
|
||||
*
|
||||
* @return Returns 0 on success or negative error code on error
|
||||
*/
|
||||
static int mipi_dsi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct mipi_dsi_info *mipi_dsi;
|
||||
struct resource *res;
|
||||
const char *lcd_panel;
|
||||
int ret = 0;
|
||||
|
||||
mipi_dsi = devm_kzalloc(&pdev->dev, sizeof(*mipi_dsi), GFP_KERNEL);
|
||||
if (!mipi_dsi)
|
||||
return -ENOMEM;
|
||||
mipi_dsi->pdev = pdev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "failed to get platform resource mem\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!devm_request_mem_region(&pdev->dev, res->start,
|
||||
resource_size(res), pdev->name))
|
||||
return -EBUSY;
|
||||
|
||||
mipi_dsi->mmio_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!mipi_dsi->mmio_base)
|
||||
return -ENOMEM;
|
||||
|
||||
mipi_dsi->irq = platform_get_irq(pdev, 0);
|
||||
if (mipi_dsi->irq < 0) {
|
||||
dev_err(&pdev->dev, "failed to get device irq\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, mipi_dsi->irq,
|
||||
mipi_dsi_irq_handler,
|
||||
0, "mipi_dsi_samsung", mipi_dsi);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request mipi dsi irq\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mipi_dsi->dphy_clk = devm_clk_get(&pdev->dev, "mipi_pllref_clk");
|
||||
if (IS_ERR(mipi_dsi->dphy_clk)) {
|
||||
dev_err(&pdev->dev, "failed to get dphy pll_ref_clk\n");
|
||||
return PTR_ERR(mipi_dsi->dphy_clk);
|
||||
}
|
||||
|
||||
mipi_dsi->cfg_clk = devm_clk_get(&pdev->dev, "mipi_cfg_clk");
|
||||
if (IS_ERR(mipi_dsi->cfg_clk)) {
|
||||
dev_err(&pdev->dev, "failed to get cfg_clk\n");
|
||||
return PTR_ERR(mipi_dsi->cfg_clk);
|
||||
}
|
||||
|
||||
ret = of_property_read_string(np, "lcd_panel", &lcd_panel);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to read lcd_panel property\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mipi_phy_reg = devm_regulator_get(&pdev->dev, "mipi-phy");
|
||||
if (IS_ERR(mipi_phy_reg)) {
|
||||
dev_err(&pdev->dev, "mipi phy power supply not found\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mipi_dsi->disp_power_on = devm_regulator_get(&pdev->dev,
|
||||
"disp-power-on");
|
||||
if (!IS_ERR(mipi_dsi->disp_power_on)) {
|
||||
ret = regulator_enable(mipi_dsi->disp_power_on);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable display "
|
||||
"power regulator, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
mipi_dsi->lcd_panel = kstrdup(lcd_panel, GFP_KERNEL);
|
||||
if (!mipi_dsi->lcd_panel) {
|
||||
dev_err(&pdev->dev, "failed to allocate lcd panel name\n");
|
||||
ret = -ENOMEM;
|
||||
goto kstrdup_fail;
|
||||
}
|
||||
|
||||
mipi_dsi->disp_mipi = mxc_dispdrv_register(&mipi_dsi_drv);
|
||||
if (IS_ERR(mipi_dsi->disp_mipi)) {
|
||||
dev_err(&pdev->dev, "mxc_dispdrv_register error\n");
|
||||
ret = PTR_ERR(mipi_dsi->disp_mipi);
|
||||
goto dispdrv_reg_fail;
|
||||
}
|
||||
|
||||
mipi_dsi->mipi_dsi_pkt_read = mipi_dsi_pkt_read;
|
||||
mipi_dsi->mipi_dsi_pkt_write = mipi_dsi_pkt_write;
|
||||
mipi_dsi->mipi_dsi_dcs_cmd = mipi_dsi_dcs_cmd;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
mxc_dispdrv_setdata(mipi_dsi->disp_mipi, mipi_dsi);
|
||||
dev_set_drvdata(&pdev->dev, mipi_dsi);
|
||||
|
||||
dev_info(&pdev->dev, "i.MX MIPI DSI driver probed\n");
|
||||
return ret;
|
||||
|
||||
dispdrv_reg_fail:
|
||||
kfree(mipi_dsi->lcd_panel);
|
||||
kstrdup_fail:
|
||||
if (mipi_dsi->disp_power_on)
|
||||
regulator_disable(mipi_dsi->disp_power_on);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mipi_dsi_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
mipi_dsi_power_off(mipi_dsi->disp_mipi);
|
||||
mipi_dsi_dphy_power_down();
|
||||
}
|
||||
|
||||
static int mipi_dsi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
mxc_dispdrv_puthandle(mipi_dsi->disp_mipi);
|
||||
mxc_dispdrv_unregister(mipi_dsi->disp_mipi);
|
||||
|
||||
if (mipi_dsi->disp_power_on)
|
||||
regulator_disable(mipi_dsi->disp_power_on);
|
||||
|
||||
kfree(mipi_dsi->lcd_panel);
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mipi_dsi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (mipi_dsi->dsi_power_on) {
|
||||
release_bus_freq(BUS_FREQ_HIGH);
|
||||
dev_dbg(dev, "mipi dsi busfreq high release.\n");
|
||||
|
||||
mipi_dsi_dphy_power_down();
|
||||
mipi_dsi->dsi_power_on = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mipi_dsi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (!mipi_dsi->dsi_power_on) {
|
||||
request_bus_freq(BUS_FREQ_HIGH);
|
||||
dev_dbg(dev, "mipi dsi busfreq high request.\n");
|
||||
|
||||
mipi_dsi_dphy_power_on(pdev);
|
||||
mipi_dsi->dsi_power_on = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops mipi_dsi_pm_ops = {
|
||||
.runtime_suspend = mipi_dsi_runtime_suspend,
|
||||
.runtime_resume = mipi_dsi_runtime_resume,
|
||||
.runtime_idle = NULL,
|
||||
};
|
||||
|
||||
static struct platform_driver mipi_dsi_driver = {
|
||||
.driver = {
|
||||
.of_match_table = imx_mipi_dsi_dt_ids,
|
||||
.name = "mxc_mipi_dsi_samsung",
|
||||
.pm = &mipi_dsi_pm_ops,
|
||||
},
|
||||
.probe = mipi_dsi_probe,
|
||||
.remove = mipi_dsi_remove,
|
||||
.shutdown = mipi_dsi_shutdown,
|
||||
};
|
||||
|
||||
static int __init mipi_dsi_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = platform_driver_register(&mipi_dsi_driver);
|
||||
if (err) {
|
||||
pr_err("mipi_dsi_driver register failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
pr_debug("MIPI DSI driver module loaded: %s\n", mipi_dsi_driver.driver.name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit mipi_dsi_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&mipi_dsi_driver);
|
||||
}
|
||||
|
||||
module_init(mipi_dsi_init);
|
||||
module_exit(mipi_dsi_cleanup);
|
||||
|
||||
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
|
||||
MODULE_DESCRIPTION("i.MX MIPI DSI driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __INCLUDE_MIPI_DSI_SAMSUNG_H
|
||||
#define __INCLUDE_MIPI_DSI_SAMSUNG_H
|
||||
|
||||
#define MIPI_DSI_VERSION (0x000)
|
||||
#define MIPI_DSI_STATUS (0x004)
|
||||
#define MIPI_DSI_RGB_STATUS (0x008)
|
||||
#define MIPI_DSI_SWRST (0x00c)
|
||||
#define MIPI_DSI_CLKCTRL (0x010)
|
||||
#define MIPI_DSI_TIMEOUT (0x014)
|
||||
#define MIPI_DSI_CONFIG (0x018)
|
||||
#define MIPI_DSI_ESCMODE (0x01c)
|
||||
#define MIPI_DSI_MDRESOL (0x020)
|
||||
#define MIPI_DSI_MVPORCH (0x024)
|
||||
#define MIPI_DSI_MHPORCH (0x028)
|
||||
#define MIPI_DSI_MSYNC (0x02c)
|
||||
#define MIPI_DSI_SDRESOL (0x030)
|
||||
#define MIPI_DSI_INTSRC (0x034)
|
||||
#define MIPI_DSI_INTMSK (0x038)
|
||||
#define MIPI_DSI_PKTHDR (0x03c)
|
||||
#define MIPI_DSI_PAYLOAD (0x040)
|
||||
#define MIPI_DSI_RXFIFO (0x044)
|
||||
#define MIPI_DSI_FIFOTHLD (0x048)
|
||||
#define MIPI_DSI_FIFOCTRL (0x04c)
|
||||
#define MIPI_DSI_MEMACCHR (0x050)
|
||||
#define MIPI_DSI_MULTI_PKT (0x078)
|
||||
#define MIPI_DSI_PLLCTRL_1G (0x090)
|
||||
#define MIPI_DSI_PLLCTRL (0x094)
|
||||
#define MIPI_DSI_PLLCTRL1 (0x098)
|
||||
#define MIPI_DSI_PLLCTRL2 (0x09c)
|
||||
#define MIPI_DSI_PLLTMR (0x0a0)
|
||||
#define MIPI_DSI_PHYCTRL_B1 (0x0a4)
|
||||
#define MIPI_DSI_PHYCTRL_B2 (0x0a8)
|
||||
#define MIPI_DSI_PHYCTRL_M1 (0x0a8)
|
||||
#define MIPI_DSI_PHYCTRL_M2 (0x0ac)
|
||||
#define MIPI_DSI_PHYTIMING (0x0b4)
|
||||
#define MIPI_DSI_PHYTIMING1 (0x0b8)
|
||||
#define MIPI_DSI_PHYTIMING2 (0x0bc)
|
||||
|
||||
#define MIPI_DSI_SWRST_SWRST (0x1 << 0)
|
||||
#define MIPI_DSI_SWRST_FUNCRST (0x1 << 16)
|
||||
#define MIPI_DSI_MAIN_HRESOL(x) (((x) & 0x7ff) << 0)
|
||||
#define MIPI_DSI_MAIN_VRESOL(x) (((x) & 0x7ff) << 16)
|
||||
#define MIPI_DSI_MAIN_STANDBY(x) (((x) & 0x1) << 31)
|
||||
#define MIPI_DSI_MAIN_VBP(x) (((x) & 0x7ff) << 0)
|
||||
#define MIPI_DSI_STABLE_VFP(x) (((x) & 0x7ff) << 16)
|
||||
#define MIPI_DSI_CMDALLOW(x) (((x) & 0xf) << 28)
|
||||
#define MIPI_DSI_MAIN_HBP(x) (((x) & 0xffff) << 0)
|
||||
#define MIPI_DSI_MAIN_HFP(x) (((x) & 0xffff) << 16)
|
||||
#define MIPI_DSI_MAIN_VSA(x) (((x) & 0x3ff) << 22)
|
||||
#define MIPI_DSI_MAIN_HSA(x) (((x) & 0xffff) << 0)
|
||||
|
||||
#define MIPI_DSI_LANE_EN(x) (((x) & 0x1f) << 0)
|
||||
#define MIPI_DSI_NUM_OF_DATALANE(x) (((x) & 0x3) << 5)
|
||||
#define MIPI_DSI_SUB_PIX_FORMAT(x) (((x) & 0x7) << 8)
|
||||
#define MIPI_DSI_MAIN_PIX_FORMAT(x) (((x) & 0x7) << 12)
|
||||
#define MIPI_DSI_SUB_VC(x) (((x) & 0x3) << 16)
|
||||
#define MIPI_DSI_MAIN_VC(x) (((x) & 0x3) << 18)
|
||||
#define MIPI_DSI_HSA_DISABLE_MODE(x) (((x) & 0x1) << 20)
|
||||
#define MIPI_DSI_HBP_DISABLE_MODE(x) (((x) & 0x1) << 21)
|
||||
#define MIPI_DSI_HFP_DISABLE_MODE(x) (((x) & 0x1) << 22)
|
||||
#define MIPI_DSI_HSE_DISABLE_MODE(x) (((x) & 0x1) << 23)
|
||||
#define MIPI_DSI_AUTO_MODE(x) (((x) & 0x1) << 24)
|
||||
#define MIPI_DSI_VIDEO_MODE(x) (((x) & 0x1) << 25)
|
||||
#define MIPI_DSI_BURST_MODE(x) (((x) & 0x1) << 26)
|
||||
#define MIPI_DSI_SYNC_IN_FORM(x) (((x) & 0x1) << 27)
|
||||
#define MIPI_DSI_EOT_R03(x) (((x) & 0x1) << 28)
|
||||
#define MIPI_DSI_MFLUSH_VS(x) (((x) & 0x1) << 29)
|
||||
|
||||
#define MIPI_DSI_DP_DN_SWAP_DATA (0x1 << 24)
|
||||
#define MIPI_DSI_PLL_EN(x) (((x) & 0x1) << 23)
|
||||
#define MIPI_DSI_PMS(x) (((x) & 0x7ffff) << 1)
|
||||
|
||||
#define MIPI_DSI_TX_REQUEST_HSCLK(x) (((x) & 0x1) << 31)
|
||||
#define MIPI_DSI_DPHY_SEL(x) (((x) & 0x1) << 29)
|
||||
#define MIPI_DSI_ESC_CLK_EN(x) (((x) & 0x1) << 28)
|
||||
#define MIPI_DSI_PLL_BYPASS(x) (((x) & 0x1) << 27)
|
||||
#define MIPI_DSI_BYTE_CLK_SRC(x) (((x) & 0x3) << 25)
|
||||
#define MIPI_DSI_BYTE_CLK_EN(x) (((x) & 0x1) << 24)
|
||||
#define MIPI_DSI_LANE_ESC_CLK_EN(x) (((x) & 0x1f) << 19)
|
||||
|
||||
#define MIPI_DSI_FORCE_STOP_STATE(x) (((x) & 0x1) << 20)
|
||||
|
||||
#define MIPI_DSI_M_TLPXCTL(x) (((x) & 0xff) << 8)
|
||||
#define MIPI_DSI_M_THSEXITCTL(x) (((x) & 0xff) << 0)
|
||||
|
||||
#define MIPI_DSI_M_TCLKPRPRCTL(x) (((x) & 0xff) << 24)
|
||||
#define MIPI_DSI_M_TCLKZEROCTL(x) (((x) & 0xff) << 16)
|
||||
#define MIPI_DSI_M_TCLKPOSTCTL(x) (((x) & 0xff) << 8)
|
||||
#define MIPI_DSI_M_TCLKTRAILCTL(x) (((x) & 0xff) << 0)
|
||||
|
||||
#define MIPI_DSI_M_THSPRPRCTL(x) (((x) & 0xff) << 16)
|
||||
#define MIPI_DSI_M_THSZEROCTL(x) (((x) & 0xff) << 8)
|
||||
#define MIPI_DSI_M_THSTRAILCTL(x) (((x) & 0xff) << 0)
|
||||
|
||||
#define MIPI_DSI_PLL_STABLE(x) (((x) & 0x1) << 31)
|
||||
#define MIPI_DSI_TX_READY_HS_CLK(x) (((x) & 0x1) << 10)
|
||||
#define MIPI_DSI_ULPS_CLK(x) (((x) & 0x1) << 9)
|
||||
#define MIPI_DSI_STOP_STATE_CLK(x) (((x) & 0x1) << 8)
|
||||
#define MIPI_DSI_ULPS_DAT(x) (((x) & 0xf) << 4)
|
||||
#define MIPI_DSI_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
|
||||
|
||||
#define INTSRC_SFR_PL_FIFO_EMPTY (0x1 << 29)
|
||||
#define INTSRC_SFR_PH_FIFO_EMPTY (0x1 << 28)
|
||||
#define INTSRC_RX_DATA_DONE (0x1 << 18)
|
||||
#define INTMSK_SFR_PL_FIFO_EMPTY (0x1 << 29)
|
||||
#define INTMSK_SFR_PH_FIFO_EMPTY (0x1 << 28)
|
||||
#define INTMSK_RX_DATA_DONE (0x1 << 18)
|
||||
|
||||
#define MIPI_DSI_STOP_STATE_CNT(x) (((x) & 0x7ff) << 21)
|
||||
#define MIPI_DSI_CMD_LPDT (0x1 << 7)
|
||||
#define MIPI_DSI_TX_LPDT (0x1 << 6)
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue