display: msm: qpic: Add QPIC display support base on DRM framework

QPIC display is used to send frame data to panel over Qualcomm Parallel
Interface Controller on MDM project.
Old QPIC display driver is base on framebuffer framework, but now
msm framebuffer driver is no longer used.
So add supoport for QPIC display driver base on tiny DRM framework.

Change-Id: I4f2434c9f9ad536e2ea56ed3daa6eb12ad56255b
Signed-off-by: Lei Chen <chenlei@codeaurora.org>
This commit is contained in:
Lei Chen 2021-03-15 15:43:12 +08:00 committed by Gerrit - the friendly Code Review server
parent dbb61136a6
commit b961099875
8 changed files with 1723 additions and 0 deletions

View File

@ -59,3 +59,13 @@ LINUXINCLUDE += -include $(srctree)/techpack/display/config/monacodispconf.h
endif
obj-$(CONFIG_DRM_MSM) += msm/
ifeq ($(CONFIG_ARCH_SDXLEMUR), y)
include $(srctree)/techpack/display/config/sdxlemurdisp.conf
endif
ifeq ($(CONFIG_ARCH_SDXLEMUR), y)
LINUXINCLUDE += -include $(srctree)/techpack/display/config/sdxlemurdispconf.h
endif
obj-$(CONFIG_DRM_QPIC_DISPLAY) += tinydrm/

4
config/sdxlemurdisp.conf Normal file
View File

@ -0,0 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (c) 2021, The Linux Foundation. All rights reserved.
export CONFIG_DRM_QPIC_DISPLAY=y

View File

@ -0,0 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#define CONFIG_DRM_QPIC_DISPLAY 1

5
tinydrm/Makefile Normal file
View File

@ -0,0 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_DRM_QPIC_DISPLAY) += qpic_display.o \
qpic_panel_ili9341.o \

1386
tinydrm/qpic_display.c Normal file

File diff suppressed because it is too large Load Diff

137
tinydrm/qpic_display.h Normal file
View File

@ -0,0 +1,137 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2014-2015, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef __QPIC_DISPLAY_H__
#define __QPIC_DISPLAY_H__
#include <linux/clk.h>
#include <linux/msm-sps.h>
#include <linux/interrupt.h>
#include <linux/interconnect.h>
#include <linux/regulator/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <drm/drm_drv.h>
#include <drm/drm_connector.h>
#include <drm/drm_simple_kms_helper.h>
#define QPIC_REG_QPIC_LCDC_CTRL 0x22000
#define QPIC_REG_LCDC_VERSION 0x22004
#define QPIC_REG_QPIC_LCDC_IRQ_EN 0x22008
#define QPIC_REG_QPIC_LCDC_IRQ_STTS 0x2200C
#define QPIC_REG_QPIC_LCDC_IRQ_CLR 0x22010
#define QPIC_REG_QPIC_LCDC_STTS 0x22014
#define QPIC_REG_QPIC_LCDC_CMD_DATA_CYCLE_CNT 0x22018
#define QPIC_REG_QPIC_LCDC_CFG0 0x22020
#define QPIC_REG_QPIC_LCDC_CFG1 0x22024
#define QPIC_REG_QPIC_LCDC_CFG2 0x22028
#define QPIC_REG_QPIC_LCDC_RESET 0x2202C
#define QPIC_REG_QPIC_LCDC_FIFO_SOF 0x22100
#define QPIC_REG_LCD_DEVICE_CMD0 0x23000
#define QPIC_REG_QPIC_LCDC_FIFO_DATA_PORT0 0x22140
#define QPIC_REG_QPIC_LCDC_FIFO_EOF 0x22180
#define QPIC_OUTP(qpic_display, off, data) \
writel_relaxed((data), (qpic_display)->qpic_base + (off))
#define QPIC_OUTPW(qpic_display, off, data) \
writew_relaxed((data), (qpic_display)->qpic_base + (off))
#define QPIC_INP(qpic_display, off) \
readl_relaxed((qpic_display)->qpic_base + (off))
#define QPIC_MAX_VSYNC_WAIT_TIME_IN_MS 500
#define QPIC_MAX_CMD_BUF_SIZE_IN_BYTES 512
#define QPIC_PINCTRL_STATE_DEFAULT "qpic_display_default"
#define QPIC_PINCTRL_STATE_SLEEP "qpic_display_sleep"
/* Structure that defines an SPS end point for a BAM pipe. */
struct qpic_sps_endpt {
struct sps_pipe *handle;
struct sps_connect config;
struct sps_register_event bam_event;
struct completion completion;
};
struct qpic_panel_config {
u32 xres;
u32 yres;
u32 bpp;
u32 type;
};
struct qpic_pinctrl_res {
struct pinctrl *pinctrl;
struct pinctrl_state *gpio_state_active;
struct pinctrl_state *gpio_state_suspend;
};
struct qpic_panel_io_desc {
int rst_gpio;
int cs_gpio;
int ad8_gpio;
int te_gpio;
int bl_gpio;
struct regulator *vdd_vreg;
struct regulator *avdd_vreg;
struct qpic_pinctrl_res pin_res;
};
struct bus_scaling_data {
u64 ab;
u64 ib;
};
struct msm_bus_path {
unsigned int num_paths;
struct bus_scaling_data *vec;
};
struct qpic_display_bus_scale_pdata {
const char *name;
unsigned int num_usecase;
struct msm_bus_path *usecase;
struct icc_path *data_bus_hdl;
u32 curr_vote;
};
struct qpic_display_data {
u32 rev;
struct platform_device *pdev;
struct drm_device drm_dev;
struct drm_simple_display_pipe pipe;
struct drm_connector conn;
struct drm_display_mode drm_mode;
bool pipe_enabled;
size_t qpic_reg_size;
u32 qpic_phys;
char __iomem *qpic_base;
u32 irq_id;
bool irq_ena;
u32 res_init;
void *cmd_buf_virt;
phys_addr_t cmd_buf_phys;
struct qpic_sps_endpt qpic_endpt;
u32 sps_init;
u32 irq_requested;
struct qpic_display_bus_scale_pdata *data_bus_pdata;
struct completion fifo_eof_comp;
bool is_qpic_on;
struct clk *qpic_clk;
struct clk *qpic_a_clk;
int (*qpic_transfer)(struct qpic_display_data *qpic_display,
u32 cmd, u8 *param, u32 len);
bool is_panel_on;
struct qpic_panel_config *panel_config;
struct qpic_panel_io_desc panel_io;
int (*panel_on)(struct qpic_display_data *qpic_display);
void (*panel_off)(struct qpic_display_data *qpic_display);
};
int get_ili_qvga_panel_config(struct qpic_display_data *qpic_display);
#endif

View File

@ -0,0 +1,91 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2014-2015, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef __QPIC_DISPLAY_PANEL_H__
#define __QPIC_DISPLAY_PANEL_H__
#include <linux/delay.h>
/**
* Macros for coding MIPI commands
*/
#define INV_SIZE 0xFFFF
/* Size of argument to MIPI command is variable */
#define OP_SIZE_PAIR(op, size) ((op<<16) | size)
/* MIPI {command, argument size} tuple */
#define LCDC_EXTRACT_OP_SIZE(op_identifier) ((op_identifier&0xFFFF))
/* extract size from command identifier */
#define LCDC_EXTRACT_OP_CMD(op_identifier) (((op_identifier>>16)&0xFFFF))
/* extract command id from command identifier */
/* MIPI standard efinitions */
#define LCDC_ADDRESS_MODE_ORDER_BOTTOM_TO_TOP 0x80
#define LCDC_ADDRESS_MODE_ORDER_RIGHT_TO_LEFT 0x40
#define LCDC_ADDRESS_MODE_ORDER_REVERSE 0x20
#define LCDC_ADDRESS_MODE_ORDER_REFRESH_BOTTOM_TO_TOP 0x10
#define LCDC_ADDRESS_MODE_ORDER_BGER_RGB 0x08
#define LCDC_ADDRESS_MODE_ORDER_REFERESH_RIGHT_TO_LEFT 0x04
#define LCDC_ADDRESS_MODE_FLIP_HORIZONTAL 0x02
#define LCDC_ADDRESS_MODE_FLIP_VERTICAL 0x01
#define LCDC_PIXEL_FORMAT_3_BITS_PER_PIXEL 0x1
#define LCDC_PIXEL_FORMAT_8_BITS_PER_PIXEL 0x2
#define LCDC_PIXEL_FORMAT_12_BITS_PER_PIXEL 0x3
#define LCDC_PIXEL_FORMAT_16_BITS_PER_PIXEL 0x5
#define LCDC_PIXEL_FORMAT_18_BITS_PER_PIXEL 0x6
#define LCDC_PIXEL_FORMAT_24_BITS_PER_PIXEL 0x7
#define LCDC_CREATE_PIXEL_FORMAT(dpi_format, dbi_format) \
(dpi_format | (dpi_format<<4))
#define POWER_MODE_IDLE_ON 0x40
#define POWER_MODE_PARTIAL_ON 0x20
#define POWER_MODE_SLEEP_ON 0x10
#define POWER_MODE_NORMAL_ON 0x08
#define POWER_MODE_DISPLAY_ON 0x04
#define LCDC_DISPLAY_MODE_SCROLLING_ON 0x80
#define LCDC_DISPLAY_MODE_INVERSION_ON 0x20
#define LCDC_DISPLAY_MODE_GAMMA_MASK 0x07
/**
* LDCc MIPI Type B supported commands
*/
#define OP_ENTER_IDLE_MODE 0x39
#define OP_ENTER_INVERT_MODE 0x21
#define OP_ENTER_NORMAL_MODE 0x13
#define OP_ENTER_PARTIAL_MODE 0x12
#define OP_ENTER_SLEEP_MODE 0x10
#define OP_EXIT_INVERT_MODE 0x20
#define OP_EXIT_SLEEP_MODE 0x11
#define OP_EXIT_IDLE_MODE 0x38
#define OP_GET_ADDRESS_MODE 0x0B /* size 1 */
#define OP_GET_BLUE_CHANNEL 0x08 /* size 1 */
#define OP_GET_DIAGNOSTIC 0x0F /* size 2 */
#define OP_GET_DISPLAY_MODE 0x0D /* size 1 */
#define OP_GET_GREEN_CHANNEL 0x07 /* size 1 */
#define OP_GET_PIXEL_FORMAT 0x0C /* size 1 */
#define OP_GET_POWER_MODE 0x0A /* size 1 */
#define OP_GET_RED_CHANNEL 0x06 /* size 1 */
#define OP_GET_SCANLINE 0x45 /* size 1 */
#define OP_GET_SIGNAL_MODE 0x0E /* size 1 */
#define OP_NOP 0x00
#define OP_READ_DDB_CONTINUE 0xA8 /* size not fixed */
#define OP_READ_DDB_START 0xA1 /* size not fixed */
#define OP_READ_MEMORY_CONTINUE 0x3E /* size not fixed */
#define OP_READ_MEMORY_START 0x2E /* size not fixed */
#define OP_SET_ADDRESS_MODE 0x36 /* size 1 */
#define OP_SET_COLUMN_ADDRESS 0x2A /* size 4 */
#define OP_SET_DISPLAY_OFF 0x28
#define OP_SET_DISPLAY_ON 0x29
#define OP_SET_GAMMA_CURVE 0x26 /* size 1 */
#define OP_SET_PAGE_ADDRESS 0x2B /* size 4 */
#define OP_SET_PARTIAL_COLUMNS 0x31 /* size 4 */
#define OP_SET_PARTIAL_ROWS 0x30 /* size 4 */
#define OP_SET_PIXEL_FORMAT 0x3A /* size 1 */
#define OP_SOFT_RESET 0x01
#define OP_WRITE_MEMORY_CONTINUE 0x3C /* size not fixed */
#define OP_WRITE_MEMORY_START 0x2C /* size not fixed */
#endif

View File

@ -0,0 +1,84 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2013-2015, 2021, The Linux Foundation. All rights reserved.
*/
#include "qpic_display.h"
#include "qpic_display_panel.h"
/**
* ILI9341 commands
*/
#define OP_ILI9341_INTERFACE_CONTROL 0xf6
#define OP_ILI9341_TEARING_EFFECT_LINE_ON 0x35
static int ili9341_on(struct qpic_display_data *qpic_display)
{
u8 param[4];
qpic_display->qpic_transfer(qpic_display, OP_SOFT_RESET, NULL, 0);
/* wait for 120 ms after reset as panel spec suggests */
msleep(120);
qpic_display->qpic_transfer(qpic_display, OP_SET_DISPLAY_OFF, NULL, 0);
/* wait for 20 ms after disply off */
msleep(20);
/* set memory access control */
param[0] = 0x48;
qpic_display->qpic_transfer(qpic_display, OP_SET_ADDRESS_MODE, param, 1);
/* wait for 20 ms after command sent as panel spec suggests */
msleep(20);
param[0] = 0x66;
qpic_display->qpic_transfer(qpic_display, OP_SET_PIXEL_FORMAT, param, 1);
/* wait for 20 ms after command sent as panel spec suggests */
msleep(20);
/* set interface */
param[0] = 1;
param[1] = 0;
param[2] = 0;
qpic_display->qpic_transfer(qpic_display, OP_ILI9341_INTERFACE_CONTROL, param, 3);
/* wait for 20 ms after command sent */
msleep(20);
/* exit sleep mode */
qpic_display->qpic_transfer(qpic_display, OP_EXIT_SLEEP_MODE, NULL, 0);
/* wait for 20 ms after command sent as panel spec suggests */
msleep(20);
/* normal mode */
qpic_display->qpic_transfer(qpic_display, OP_ENTER_NORMAL_MODE, NULL, 0);
/* wait for 20 ms after command sent as panel spec suggests */
msleep(20);
/* display on */
qpic_display->qpic_transfer(qpic_display, OP_SET_DISPLAY_ON, NULL, 0);
/* wait for 20 ms after command sent as panel spec suggests */
msleep(20);
param[0] = 0;
qpic_display->qpic_transfer(qpic_display, OP_ILI9341_TEARING_EFFECT_LINE_ON, param, 1);
return 0;
}
static void ili9341_off(struct qpic_display_data *qpic_display)
{
qpic_display->qpic_transfer(qpic_display, OP_SET_DISPLAY_OFF, NULL, 0);
/* wait for 20 ms after display off */
msleep(20);
}
static struct qpic_panel_config ili_qvga_panel = {
.xres = 320,
.yres = 480,
.bpp = 16,
};
int get_ili_qvga_panel_config(struct qpic_display_data *qpic_display)
{
qpic_display->panel_config = &ili_qvga_panel;
qpic_display->panel_on = ili9341_on;
qpic_display->panel_off = ili9341_off;
}