Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 8c186f7abd7fde6db432f2f4e91086e68906cbf7 Mon Sep 17 00:00:00 2001
- From: b19715 <b19715@freescale.com>
- Date: Wed, 17 Oct 2018 10:10:37 -0400
- Subject: [PATCH 03/11] Add ST7789S MPU LCD support for iMX6UL board
- Updated for L4.9.11 release
- ---
- arch/arm/boot/dts/Makefile | 1 +
- arch/arm/boot/dts/imx6ul-14x14-evk-i80lcd.dts | 197 +++
- arch/arm/configs/imx_v7_defconfig | 1 +
- drivers/video/fbdev/mxc/Kconfig | 4 +
- drivers/video/fbdev/mxc/Makefile | 1 +
- drivers/video/fbdev/mxc/mxsfb_st7789s_qvga.c | 180 +++
- drivers/video/fbdev/mxsfb.c | 1196 ++++++++++-------
- drivers/video/fbdev/mxsfb.h | 371 +++++
- include/uapi/linux/mxcfb.h | 3 +
- 9 files changed, 1487 insertions(+), 467 deletions(-)
- create mode 100644 arch/arm/boot/dts/imx6ul-14x14-evk-i80lcd.dts
- create mode 100644 drivers/video/fbdev/mxc/mxsfb_st7789s_qvga.c
- create mode 100644 drivers/video/fbdev/mxsfb.h
- diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
- index 5f9cf31dc0b8..4969795383df 100644
- --- a/arch/arm/boot/dts/Makefile
- +++ b/arch/arm/boot/dts/Makefile
- @@ -485,6 +485,7 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
- imx6ul-14x14-evk-btwifi.dtb \
- imx6ul-14x14-evk-btwifi-oob.dtb \
- imx6ul-14x14-evk-csi.dtb \
- + imx6ul-14x14-evk-i80lcd.dtb \
- imx6ul-14x14-evk-emmc.dtb \
- imx6ul-14x14-evk-gpmi-weim.dtb \
- imx6ul-14x14-evk-usb-certi.dtb \
- diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-i80lcd.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-i80lcd.dts
- new file mode 100644
- index 000000000000..9d7169877205
- --- /dev/null
- +++ b/arch/arm/boot/dts/imx6ul-14x14-evk-i80lcd.dts
- @@ -0,0 +1,197 @@
- +/*
- + * Copyright (C) 2015 Freescale Semiconductor, Inc.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +/dts-v1/;
- +
- +#include <dt-bindings/input/input.h>
- +#include "imx6ul.dtsi"
- +
- +/ {
- + model = "Freescale i.MX6 UltraLite 14x14 EVK Board";
- + compatible = "fsl,imx6ul-14x14-evk", "fsl,imx6ul";
- +
- + chosen {
- + stdout-path = &uart1;
- + };
- +
- + memory {
- + reg = <0x80000000 0x20000000>;
- + };
- +
- + pxp_v4l2 {
- + compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
- + status = "okay";
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + reg_sd1_vmmc: regulator@1 {
- + compatible = "regulator-fixed";
- + regulator-name = "VSD_3V3";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
- + enable-active-high;
- + };
- + };
- +};
- +
- +&cpu0 {
- + arm-supply = <®_arm>;
- + soc-supply = <®_soc>;
- +};
- +
- +&clks {
- + assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
- + assigned-clock-rates = <786432000>;
- +};
- +
- +&gpc {
- + fsl,cpu_pupscr_sw2iso = <0x1>;
- + fsl,cpu_pupscr_sw = <0x0>;
- + fsl,cpu_pdnscr_iso2sw = <0x1>;
- + fsl,cpu_pdnscr_iso = <0x1>;
- + fsl,wdog-reset = <1>; /* watchdog select of reset source */
- + fsl,ldo-bypass = <0>; /* DCDC, ldo-enable */
- +};
- +
- +&lcdif {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_lcdif_dat
- + &pinctrl_lcdif_ctrl>;
- + display = <&display0>;
- + status = "okay";
- +
- + display0: display {
- + mpu-mode;
- + lcd_reset_gpio = <&gpio3 14 0>;
- + lcd_panel = "ST7789S-QVGA";
- + };
- +};
- +
- +&pxp {
- + status = "okay";
- +};
- +
- +&tsc {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_tsc>;
- + status = "okay";
- + xnur-gpio = <&gpio1 3 0>;
- + measure_delay_time = <0xffff>;
- + pre_charge_time = <0xfff>;
- +};
- +
- +&uart1 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&pinctrl_uart1>;
- + status = "okay";
- +};
- +
- +&usbotg1 {
- + dr_mode = "peripheral";
- + status = "okay";
- +};
- +
- +&usbotg2 {
- + dr_mode = "host";
- + disable-over-current;
- + status = "okay";
- +};
- +
- +&usdhc1 {
- + pinctrl-names = "default", "state_100mhz", "state_200mhz";
- + pinctrl-0 = <&pinctrl_usdhc1>;
- + pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
- + pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
- + cd-gpios = <&gpio1 19 0>;
- + keep-power-in-suspend;
- + enable-sdio-wakeup;
- + vmmc-supply = <®_sd1_vmmc>;
- + status = "okay";
- +};
- +
- +&iomuxc {
- + imx6ul-evk {
- + pinctrl_lcdif_dat: lcdifdatgrp {
- + fsl,pins = <
- + MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79
- + MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79
- + MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79
- + MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79
- + MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79
- + MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79
- + MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79
- + MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79
- + >;
- + };
- +
- + pinctrl_lcdif_ctrl: lcdifctrlgrp {
- + fsl,pins = <
- + MX6UL_PAD_LCD_CLK__LCDIF_WR_RWN 0x79
- + MX6UL_PAD_LCD_ENABLE__LCDIF_RD_E 0x79
- + MX6UL_PAD_LCD_HSYNC__LCDIF_RS 0x79
- + MX6UL_PAD_LCD_RESET__LCDIF_CS 0x79
- + /* used for lcd reset */
- + MX6UL_PAD_LCD_DATA09__GPIO3_IO14 0x79
- + >;
- + };
- +
- + pinctrl_uart1: uart1grp {
- + fsl,pins = <
- + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
- + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
- + >;
- + };
- +
- + pinctrl_usdhc1: usdhc1grp {
- + fsl,pins = <
- + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
- + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071
- + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
- + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
- + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
- + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
- + >;
- + };
- +
- + pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
- + fsl,pins = <
- + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9
- + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9
- + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
- + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
- + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
- + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
- + >;
- + };
- +
- + pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
- + fsl,pins = <
- + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9
- + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9
- + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
- + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
- + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
- + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
- + >;
- + };
- +
- + pinctrl_tsc: tscgrp {
- + fsl,pins = <
- + MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
- + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
- + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0
- + MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xb0
- + >;
- + };
- + };
- +};
- diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
- index 15b47de9da6c..98b3ba8db058 100644
- --- a/arch/arm/configs/imx_v7_defconfig
- +++ b/arch/arm/configs/imx_v7_defconfig
- @@ -246,6 +246,7 @@ CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E=y
- CONFIG_FB_MXC_LDB=y
- CONFIG_FB_MXC_HDMI=y
- CONFIG_FB_MXS_SII902X=y
- +CONFIG_FB_MXS_ST7789S_QVGA=y
- CONFIG_FB_MXC_DCIC=m
- CONFIG_FB_MXC_ADV7535=y
- CONFIG_HANNSTAR_CABC=y
- diff --git a/drivers/video/fbdev/mxc/Kconfig b/drivers/video/fbdev/mxc/Kconfig
- index 0b79ee371c6d..a34c52393069 100644
- --- a/drivers/video/fbdev/mxc/Kconfig
- +++ b/drivers/video/fbdev/mxc/Kconfig
- @@ -79,6 +79,10 @@ config FB_MXS_SII902X
- tristate "Si Image SII9022 DVI/HDMI Interface Chip"
- depends on FB_MXS && I2C
- +config FB_MXS_ST7789S_QVGA
- + tristate "ST7789S QVGA MPU Display"
- + depends on FB_MXS
- +
- config FB_MXC_DCIC
- tristate "MXC DCIC"
- depends on FB_MXC_SYNC_PANEL
- diff --git a/drivers/video/fbdev/mxc/Makefile b/drivers/video/fbdev/mxc/Makefile
- index a910a3a716ed..81650ec53fcf 100644
- --- a/drivers/video/fbdev/mxc/Makefile
- +++ b/drivers/video/fbdev/mxc/Makefile
- @@ -12,5 +12,6 @@ obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxc_dispdrv.o mxc_lcdif.o mxc_ipuv3_fb.o
- obj-$(CONFIG_FB_MXC_EINK_PANEL) += mxc_epdc_fb.o
- obj-$(CONFIG_FB_MXC_EINK_V2_PANEL) += mxc_epdc_v2_fb.o
- obj-$(CONFIG_FB_MXS_SII902X) += mxsfb_sii902x.o
- +obj-$(CONFIG_FB_MXS_ST7789S_QVGA) += mxsfb_st7789s_qvga.o
- obj-$(CONFIG_FB_MXC_DCIC) += mxc_dcic.o
- obj-$(CONFIG_HANNSTAR_CABC) += hannstar_cabc.o
- diff --git a/drivers/video/fbdev/mxc/mxsfb_st7789s_qvga.c b/drivers/video/fbdev/mxc/mxsfb_st7789s_qvga.c
- new file mode 100644
- index 000000000000..ab8bd84bf546
- --- /dev/null
- +++ b/drivers/video/fbdev/mxc/mxsfb_st7789s_qvga.c
- @@ -0,0 +1,180 @@
- +/*
- + * Copyright (C) 2016 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.
- + */
- +
- +#include <linux/types.h>
- +#include <linux/init.h>
- +#include <linux/delay.h>
- +#include <linux/err.h>
- +#include <linux/io.h>
- +
- +#include "../mxsfb.h"
- +
- +static struct fb_videomode st7789s_lcd_modedb[] = {
- + {
- + "ST7789S-QVGA", 60, 240, 320, 200000,
- + 0, 0,
- + 0, 0,
- + 0, 0,
- + 0,
- + FB_VMODE_NONINTERLACED,
- + 0,
- + },
- +};
- +
- +static struct mpu_lcd_config lcd_config = {
- + .bus_mode = MPU_BUS_8080,
- + .interface_width = 8,
- + .panel_bpp = 16,
- +};
- +void mpu_st7789s_get_lcd_videomode(struct fb_videomode **mode, int *size,
- + struct mpu_lcd_config **data)
- +{
- + *mode = &st7789s_lcd_modedb[0];
- + *size = ARRAY_SIZE(st7789s_lcd_modedb);
- + *data = &lcd_config;
- +}
- +
- +int mpu_st7789s_lcd_setup(struct mxsfb_info * mxsfb)
- +{
- + if (mxsfb == NULL)
- + return -1;
- +
- + /* Sleep out */
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x11);
- +
- + /* Analog setting */
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xB2);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x0C);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x0C);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x33);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x33);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xB7);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x35);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xBB);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x35);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xC0);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x2C);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xC2);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x01);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xC3);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x06);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xC4);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x20);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xC6);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0xE5);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xD0);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0xA4);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0xB1);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x55);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x90);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xE8);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x40);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x10);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xB8);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x2A);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x2B);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x15);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x75);
- +
- + /* Gamma setting */
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xE0);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0xE0);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x02);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x07);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x0B);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x1A);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x37);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x54);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x40);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x29);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x12);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x12);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x12);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x17);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xE1);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0xE0);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x02);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x07);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x05);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x25);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x37);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x44);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x45);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x1C);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x18);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x16);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x1C);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x1D);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x36);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
- +
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x3A);
- + if (mxsfb->mpu_lcd_sigs->panel_bpp == 16)
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x55);
- + else
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x66); /* 18 bpp */
- +
- + /* Set row address */
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x2A);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, (((st7789s_lcd_modedb[0].xres - 1) >> 8) & 0xFF));
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, ((st7789s_lcd_modedb[0].xres - 1) & 0xFF));
- +
- + /* Set column address */
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x2B);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, (((st7789s_lcd_modedb[0].yres - 1) >> 8) & 0xFF));
- + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, ((st7789s_lcd_modedb[0].yres - 1) & 0xFF));
- +
- + /* Display on */
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x29);
- +
- + /* Memory write */
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x2C);
- +
- + return 0;
- +}
- +
- +int mpu_st7789s_lcd_poweroff(struct mxsfb_info * mxsfb)
- +{
- + /* Display off */
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x28);
- +
- + /* Sleep in */
- + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x10);
- +
- + return 0;
- +}
- diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c
- index 0d4fe02e3031..17fe13e4b53b 100644
- --- a/drivers/video/fbdev/mxsfb.c
- +++ b/drivers/video/fbdev/mxsfb.c
- @@ -44,6 +44,7 @@
- #include <linux/console.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- +#include <linux/delay.h>
- #include <linux/of_device.h>
- #include <linux/of_gpio.h>
- #include <linux/pm_qos.h>
- @@ -64,210 +65,18 @@
- #include <linux/uaccess.h>
- #include "mxc/mxc_dispdrv.h"
- +#include "mxsfb.h"
- -#define REG_SET 4
- -#define REG_CLR 8
- -
- -#define LCDC_CTRL 0x00
- -#define LCDC_CTRL1 0x10
- -#define LCDC_V4_CTRL2 0x20
- -#define LCDC_V3_TRANSFER_COUNT 0x20
- -#define LCDC_V4_TRANSFER_COUNT 0x30
- -#define LCDC_V4_CUR_BUF 0x40
- -#define LCDC_V4_NEXT_BUF 0x50
- -#define LCDC_V3_CUR_BUF 0x30
- -#define LCDC_V3_NEXT_BUF 0x40
- -#define LCDC_TIMING 0x60
- -#define LCDC_VDCTRL0 0x70
- -#define LCDC_VDCTRL1 0x80
- -#define LCDC_VDCTRL2 0x90
- -#define LCDC_VDCTRL3 0xa0
- -#define LCDC_VDCTRL4 0xb0
- -#define LCDC_DVICTRL0 0xc0
- -#define LCDC_DVICTRL1 0xd0
- -#define LCDC_DVICTRL2 0xe0
- -#define LCDC_DVICTRL3 0xf0
- -#define LCDC_DVICTRL4 0x100
- -#define LCDC_V4_DATA 0x180
- -#define LCDC_V3_DATA 0x1b0
- -#define LCDC_V4_DEBUG0 0x1d0
- -#define LCDC_V3_DEBUG0 0x1f0
- -#define LCDC_AS_CTRL 0x210
- -#define LCDC_AS_BUF 0x220
- -#define LCDC_AS_NEXT_BUF 0x230
- -
- -#define CTRL_SFTRST (1 << 31)
- -#define CTRL_CLKGATE (1 << 30)
- -#define CTRL_BYPASS_COUNT (1 << 19)
- -#define CTRL_VSYNC_MODE (1 << 18)
- -#define CTRL_DOTCLK_MODE (1 << 17)
- -#define CTRL_DATA_SELECT (1 << 16)
- -#define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10)
- -#define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3)
- -#define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8)
- -#define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3)
- -#define CTRL_MASTER (1 << 5)
- -#define CTRL_DF16 (1 << 3)
- -#define CTRL_DF18 (1 << 2)
- -#define CTRL_DF24 (1 << 1)
- -#define CTRL_RUN (1 << 0)
- -
- -#define CTRL1_RECOVERY_ON_UNDERFLOW (1 << 24)
- -#define CTRL1_FIFO_CLEAR (1 << 21)
- -#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
- -#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
- -#define CTRL1_OVERFLOW_IRQ_EN (1 << 15)
- -#define CTRL1_UNDERFLOW_IRQ_EN (1 << 14)
- -#define CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13)
- -#define CTRL1_VSYNC_EDGE_IRQ_EN (1 << 12)
- -#define CTRL1_OVERFLOW_IRQ (1 << 11)
- -#define CTRL1_UNDERFLOW_IRQ (1 << 10)
- -#define CTRL1_CUR_FRAME_DONE_IRQ (1 << 9)
- -#define CTRL1_VSYNC_EDGE_IRQ (1 << 8)
- -#define CTRL1_IRQ_ENABLE_MASK (CTRL1_OVERFLOW_IRQ_EN | \
- - CTRL1_UNDERFLOW_IRQ_EN | \
- - CTRL1_CUR_FRAME_DONE_IRQ_EN | \
- - CTRL1_VSYNC_EDGE_IRQ_EN)
- -#define CTRL1_IRQ_ENABLE_SHIFT 12
- -#define CTRL1_IRQ_STATUS_MASK (CTRL1_OVERFLOW_IRQ | \
- - CTRL1_UNDERFLOW_IRQ | \
- - CTRL1_CUR_FRAME_DONE_IRQ | \
- - CTRL1_VSYNC_EDGE_IRQ)
- -#define CTRL1_IRQ_STATUS_SHIFT 8
- -
- -#define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21)
- -
- -#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
- -#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
- -#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)
- -#define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff)
- -
- -
- -#define VDCTRL0_ENABLE_PRESENT (1 << 28)
- -#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
- -#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
- -#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25)
- -#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24)
- -#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
- -#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
- -#define VDCTRL0_HALF_LINE (1 << 19)
- -#define VDCTRL0_HALF_LINE_MODE (1 << 18)
- -#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
- -#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
- -
- -#define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
- -#define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
- -
- -#define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29)
- -#define VDCTRL3_VSYNC_ONLY (1 << 28)
- -#define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16)
- -#define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff)
- -#define SET_VERT_WAIT_CNT(x) ((x) & 0xffff)
- -#define GET_VERT_WAIT_CNT(x) ((x) & 0xffff)
- -
- -#define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */
- -#define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */
- -#define VDCTRL4_SYNC_SIGNALS_ON (1 << 18)
- -#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
- -
- -#define DEBUG0_HSYNC (1 < 26)
- -#define DEBUG0_VSYNC (1 < 25)
- -
- -#define MIN_XRES 120
- -#define MIN_YRES 120
- -
- -#define RED 0
- -#define GREEN 1
- -#define BLUE 2
- -#define TRANSP 3
- -
- -#define STMLCDIF_8BIT 1 /** pixel data bus to the display is of 8 bit width */
- -#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
- -#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
- -#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
- -
- -#define FB_SYNC_OE_LOW_ACT 0x80000000
- -#define FB_SYNC_CLK_LAT_FALL 0x40000000
- -
- -enum mxsfb_devtype {
- - MXSFB_V3,
- - MXSFB_V4,
- - MXSFB_V5,
- -};
- -
- -/* CPU dependent register offsets */
- -struct mxsfb_devdata {
- - unsigned transfer_count;
- - unsigned cur_buf;
- - unsigned next_buf;
- - unsigned debug0;
- - unsigned hs_wdth_mask;
- - unsigned hs_wdth_shift;
- - unsigned ipversion;
- - u32 flags;
- -};
- -
- -struct mxsfb_layer;
- -
- -struct mxsfb_layer_ops {
- - void (*enable)(struct mxsfb_layer *ofb);
- - void (*disable)(struct mxsfb_layer *ofb);
- - void (*setup)(struct mxsfb_layer *ofb);
- -};
- -
- -struct mxsfb_layer {
- - struct fb_info *ol_fb;
- - int id;
- - int registered;
- - atomic_t usage;
- - int blank_state;
- - uint32_t global_alpha;
- -
- - struct mxsfb_layer_ops *ops;
- -
- - struct device *dev;
- - void __iomem *video_mem;
- - unsigned long video_mem_phys;
- - size_t video_mem_size;
- -
- - struct mxsfb_info *fbi;
- -};
- -
- -#define NAME_LEN 32
- -
- -struct mxsfb_info {
- - struct fb_info *fb_info;
- - struct platform_device *pdev;
- - struct clk *clk_pix;
- - struct clk *clk_axi;
- - struct clk *clk_disp_axi;
- - bool clk_pix_enabled;
- - bool clk_axi_enabled;
- - bool clk_disp_axi_enabled;
- - void __iomem *base; /* registers */
- - u32 sync; /* record display timing polarities */
- - unsigned allocated_size;
- - int enabled;
- - unsigned ld_intf_width;
- - unsigned dotclk_delay;
- - const struct mxsfb_devdata *devdata;
- - struct regulator *reg_lcd;
- - bool wait4vsync;
- - struct completion vsync_complete;
- - struct completion flip_complete;
- - int cur_blank;
- - int restore_blank;
- - char disp_dev[NAME_LEN];
- - struct mxc_dispdrv_handle *dispdrv;
- - int id;
- - struct fb_var_screeninfo var;
- - struct pm_qos_request pm_qos_req;
- -
- - char disp_videomode[NAME_LEN];
- -
- -#ifdef CONFIG_FB_MXC_OVERLAY
- - struct mxsfb_layer overlay;
- +static struct mpu_match_lcd mpu_lcd_db[] = {
- +#ifdef CONFIG_FB_MXS_ST7789S_QVGA
- + {
- + "ST7789S-QVGA",
- + {mpu_st7789s_get_lcd_videomode, mpu_st7789s_lcd_setup, mpu_st7789s_lcd_poweroff}
- + },
- #endif
- + {
- + "", {NULL, NULL}
- + }
- };
- #define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
- @@ -281,6 +90,7 @@ struct mxsfb_info {
- static const struct mxsfb_devdata mxsfb_devdata[] = {
- [MXSFB_V3] = {
- .transfer_count = LCDC_V3_TRANSFER_COUNT,
- + .data = LCDC_V3_DATA,
- .cur_buf = LCDC_V3_CUR_BUF,
- .next_buf = LCDC_V3_NEXT_BUF,
- .debug0 = LCDC_V3_DEBUG0,
- @@ -291,6 +101,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
- },
- [MXSFB_V4] = {
- .transfer_count = LCDC_V4_TRANSFER_COUNT,
- + .data = LCDC_V4_DATA,
- .cur_buf = LCDC_V4_CUR_BUF,
- .next_buf = LCDC_V4_NEXT_BUF,
- .debug0 = LCDC_V4_DEBUG0,
- @@ -559,6 +370,322 @@ static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf)
- return chan << bf->offset;
- }
- +static int mxsfb_mpu_wait_for_ready(struct mxsfb_info *host)
- +{
- + unsigned int val;
- + int timeout = 0;
- +
- + // Check for running
- + val = readl(host->base + LCDC_CTRL);
- + while(val & CTRL_RUN) {
- + mdelay(1);
- + timeout ++;
- + if (timeout >= 1000) {
- + dev_err(&host->pdev->dev, "mxsfb_mpu_wait_for_ready timeout!\n");
- + return -ETIME;
- + }
- + val = readl(host->base + LCDC_CTRL);
- + }
- +
- + return 0;
- +}
- +unsigned int mxsfb_mpu_access(struct mxsfb_info *host, int mode, int rw, int data)
- +{
- + unsigned int val, wordlen, ret = 0;
- +
- + if (mxsfb_mpu_wait_for_ready(host) != 0)
- + return 0;
- +
- + writel(CTRL_MASTER,
- + host->base + LCDC_CTRL + REG_CLR);
- +
- + writel(CTRL1_BYTE_PACKING_FORMAT_MASK,
- + host->base + LCDC_CTRL1 + REG_CLR);
- + val = readl(host->base + LCDC_CTRL);
- + wordlen = CTRL_GET_WORD_LENGTH(val);
- + writel(CTRL_WORD_LENGTH_MASK,
- + host->base + LCDC_CTRL + REG_CLR);
- +
- + writel(CTRL_YCBCR422_INPUT |
- + CTRL_INPUT_DATA_SWIZZLE_MASK,
- + host->base + LCDC_CTRL + REG_CLR);
- +
- + switch (host->mpu_lcd_sigs->interface_width)
- + {
- + case 8:
- + writel((0x1 << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
- + host->base + LCDC_CTRL1 + REG_SET);
- + writel(CTRL_WORD_LENGTH_8BIT,
- + host->base + LCDC_CTRL + REG_SET);
- + break;
- + case 16:
- + writel((0x3 << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
- + host->base + LCDC_CTRL1 + REG_SET);
- + writel(CTRL_WORD_LENGTH_16BIT,
- + host->base + LCDC_CTRL + REG_SET);
- + break;
- + }
- +
- + val = readl(host->base + host->devdata->transfer_count);
- + val &= ~(TRANSFER_COUNT_H_COUNT_MASK |
- + TRANSFER_COUNT_V_COUNT_MASK);
- + val |= (1 << TRANSFER_COUNT_V_COUNT_OFFSET) |
- + (1 << TRANSFER_COUNT_H_COUNT_OFFSET);
- + writel(val, host->base + host->devdata->transfer_count);
- +
- + if(mode == MPU_CMD)
- + {
- + if (host->mpu_lcd_sigs->lcd_rs_is_gpio)
- + gpio_set_value(host->mpu_lcd_sigs->lcd_rs_gpio, 0);
- + writel(CTRL_DATA_SELECT,
- + host->base + LCDC_CTRL + REG_CLR);
- + }
- + else
- + {
- + if (host->mpu_lcd_sigs->lcd_rs_is_gpio)
- + gpio_set_value(host->mpu_lcd_sigs->lcd_rs_gpio, 1);
- + writel(CTRL_DATA_SELECT,
- + host->base + LCDC_CTRL + REG_SET);
- + }
- +
- + if(rw == MPU_READ)
- + {
- + writel(CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_MASK,
- + host->base + LCDC_V4_CTRL2 + REG_CLR);
- + writel((0x1 << CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_OFFSET),
- + host->base + LCDC_V4_CTRL2 + REG_SET);
- +
- + writel(CTRL_READ_WRITEB,
- + host->base + LCDC_CTRL + REG_SET);
- + writel(CTRL_RUN,
- + host->base + LCDC_CTRL + REG_SET);
- + }
- + else
- + {
- + writel(CTRL_READ_WRITEB,
- + host->base + LCDC_CTRL + REG_CLR);
- + writel(CTRL_RUN,
- + host->base + LCDC_CTRL + REG_SET);
- +
- + writel(data,
- + host->base + host->devdata->data);
- + }
- +
- + val = readl(host->base + LCDC_CTRL);
- + while(val & CTRL_RUN)
- + {
- + if(rw == MPU_READ)
- + ret = readl(host->base + host->devdata->data);
- +
- + val = readl(host->base + LCDC_CTRL);
- + }
- +
- + writel(CTRL_MASTER,
- + host->base + LCDC_CTRL + REG_SET);
- +
- + writel(CTRL_WORD_LENGTH_MASK,
- + host->base + LCDC_CTRL + REG_CLR);
- + writel((wordlen << CTRL_WORD_LENGTH_OFFSET),
- + host->base + LCDC_CTRL + REG_SET); // 32 bits valid data
- + writel(CTRL1_BYTE_PACKING_FORMAT_MASK,
- + host->base + LCDC_CTRL1 + REG_CLR);
- + writel((0xF << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
- + host->base + LCDC_CTRL1 + REG_SET); // 32 bits valid data
- +
- + writel(CTRL_MASTER,
- + host->base + LCDC_CTRL + REG_SET);
- +
- + // For idle, set LCD_RS to high
- + if (host->mpu_lcd_sigs->lcd_rs_is_gpio)
- + gpio_set_value(host->mpu_lcd_sigs->lcd_rs_gpio, 1);
- +
- + return ret;
- +}
- +
- +int mxsfb_mpu_refresh_panel(struct mxsfb_info *host)
- +{
- + if (mxsfb_mpu_wait_for_ready(host) != 0)
- + return -ETIME;
- +
- + writel(CTRL_MASTER,
- + host->base + LCDC_CTRL + REG_SET);
- + writel(CTRL_RUN,
- + host->base + LCDC_CTRL + REG_SET);
- + return 0;
- +}
- +
- +void mxsfb_mpu_setup_refresh_data(struct mxsfb_info *host)
- +{
- + unsigned int val;
- +
- + if (mxsfb_mpu_wait_for_ready(host) != 0)
- + return;
- +
- + val = readl(host->base + host->devdata->transfer_count);
- + val &= ~(TRANSFER_COUNT_H_COUNT_MASK |
- + TRANSFER_COUNT_V_COUNT_MASK);
- + val |= (host->var.xres << TRANSFER_COUNT_H_COUNT_OFFSET) |
- + (host->var.yres << TRANSFER_COUNT_V_COUNT_OFFSET);
- + writel(val, host->base + host->devdata->transfer_count);
- +
- + writel(CTRL_READ_WRITEB,
- + host->base + LCDC_CTRL + REG_CLR);
- + writel(CTRL_BYPASS_COUNT,
- + host->base + LCDC_CTRL + REG_CLR);
- + writel(CTRL_DATA_SELECT,
- + host->base + LCDC_CTRL + REG_SET);
- + if (host->mpu_lcd_sigs->lcd_rs_is_gpio)
- + gpio_set_value(host->mpu_lcd_sigs->lcd_rs_gpio, 1);
- +
- + if (host->mpu_lcd_sigs->panel_bpp == 16) {
- + writel(CTRL_YCBCR422_INPUT |
- + (1 << CTRL_INPUT_DATA_SWIZZLE_OFFSET),
- + host->base + LCDC_CTRL + REG_SET);
- + }
- +}
- +
- +static void mxsfb_mpu_setup_interface(struct mxsfb_info *host)
- +{
- + writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
- + writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_CLR);
- +
- + /* Setup the bus protocol */
- + if (host->mpu_lcd_sigs->bus_mode == MPU_BUS_8080)
- + writel(CTRL1_MODE86,
- + host->base + LCDC_CTRL1 + REG_CLR);
- + else
- + writel(CTRL1_MODE86,
- + host->base + LCDC_CTRL1 + REG_SET);
- +
- + writel(CTRL1_BUSY_ENABLE,
- + host->base + LCDC_CTRL1 + REG_CLR);
- +
- + /* Take display out of reset */
- + writel(CTRL1_RESET,
- + host->base + LCDC_CTRL1 + REG_SET);
- + if (host->mpu_lcd_sigs->lcd_reset_is_gpio)
- + gpio_set_value(host->mpu_lcd_sigs->lcd_reset_gpio, 1);
- +
- + /* VSYNC is an input by default */
- + writel(VDCTRL0_VSYNC_OEB,
- + host->base + LCDC_VDCTRL0 + REG_SET);
- +
- + /*
- + * Make sure we do a high-to-low transition to reset the panel.
- + * First make it low for 100 msec, hi for 10 msec, low for 10 msec,
- + * then hi.
- + */
- + writel(CTRL1_RESET,
- + host->base + LCDC_CTRL1 + REG_CLR); /* low */
- + if (host->mpu_lcd_sigs->lcd_reset_is_gpio)
- + gpio_set_value(host->mpu_lcd_sigs->lcd_reset_gpio, 0);
- +
- + msleep(100);
- +
- + writel(CTRL1_RESET,
- + host->base + LCDC_CTRL1 + REG_SET); /* high */
- + if (host->mpu_lcd_sigs->lcd_reset_is_gpio)
- + gpio_set_value(host->mpu_lcd_sigs->lcd_reset_gpio, 1);
- +
- + msleep(10);
- +
- + writel(CTRL1_RESET,
- + host->base + LCDC_CTRL1 + REG_CLR); /* low */
- + if (host->mpu_lcd_sigs->lcd_reset_is_gpio)
- + gpio_set_value(host->mpu_lcd_sigs->lcd_reset_gpio, 0);
- +
- + /* For some panel, Reset must be held low at least 30 uSec
- + * Therefore, we'll hold it low for about 10 mSec just to be sure.
- + * Then we'll wait 1 mSec afterwards.
- + */
- + msleep(10);
- + writel(CTRL1_RESET,
- + host->base + LCDC_CTRL1 + REG_SET); /* high */
- + if (host->mpu_lcd_sigs->lcd_reset_is_gpio)
- + gpio_set_value(host->mpu_lcd_sigs->lcd_reset_gpio, 1);
- + msleep(1);
- +
- + writel(CTRL_DATA_SHIFT_DIR,
- + host->base + LCDC_CTRL + REG_CLR);
- +
- + writel(CTRL_SHIFT_NUM_BITS_MASK,
- + host->base + LCDC_CTRL + REG_CLR);
- +
- + writel(CTRL2_OUTSTANDING_REQS_MASK,
- + host->base + LCDC_V4_CTRL2 + REG_CLR);
- + writel(CTRL2_OUTSTANDING_REQS_REQ_8,
- + host->base + LCDC_V4_CTRL2 + REG_SET);
- +
- + /* Recover on underflow */
- + writel(CTRL1_RECOVERY_ON_UNDERFLOW,
- + host->base + LCDC_CTRL1 + REG_SET);
- +
- + /* Configure the input pixel format */
- + writel(CTRL_YCBCR422_INPUT |
- + CTRL_WORD_LENGTH_MASK |
- + CTRL_INPUT_DATA_SWIZZLE_MASK |
- + CTRL_DATA_FORMAT_16_BIT |
- + CTRL_DATA_FORMAT_18_BIT |
- + CTRL_DATA_FORMAT_24_BIT,
- + host->base + LCDC_CTRL + REG_CLR);
- + writel(CTRL1_BYTE_PACKING_FORMAT_MASK,
- + host->base + LCDC_CTRL1 + REG_CLR);
- + switch (host->mpu_lcd_sigs->panel_bpp) {
- + case 16:
- + writel((0xF << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
- + host->base + LCDC_CTRL1 + REG_SET);
- + writel(CTRL_WORD_LENGTH_16BIT |
- + (0 << CTRL_INPUT_DATA_SWIZZLE_OFFSET),
- + host->base + LCDC_CTRL + REG_SET);
- + break;
- + case 18:
- + writel((0xF << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
- + host->base + LCDC_CTRL1 + REG_SET);
- + writel(CTRL_WORD_LENGTH_18BIT |
- + (0 << CTRL_INPUT_DATA_SWIZZLE_OFFSET),
- + host->base + LCDC_CTRL + REG_SET);
- + break;
- + case 24:
- + default:
- + writel((0xF << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
- + host->base + LCDC_CTRL1 + REG_SET);
- + writel(CTRL_WORD_LENGTH_24BIT|
- + (0 << CTRL_INPUT_DATA_SWIZZLE_OFFSET),
- + host->base + LCDC_CTRL + REG_SET);
- + break;
- + }
- +
- + /* Configure the output bus width */
- + writel(CTRL_LCD_DATABUS_WIDTH_MASK,
- + host->base + LCDC_CTRL + REG_CLR);
- + switch (host->mpu_lcd_sigs->interface_width) {
- + case 8:
- + writel(CTRL_LCD_DATABUS_WIDTH_8BIT,
- + host->base + LCDC_CTRL + REG_SET);
- + break;
- + case 16:
- + writel(CTRL_LCD_DATABUS_WIDTH_16BIT,
- + host->base + LCDC_CTRL + REG_SET);
- + break;
- + case 18:
- + writel(CTRL_LCD_DATABUS_WIDTH_18BIT,
- + host->base + LCDC_CTRL + REG_SET);
- + break;
- + case 24:
- + default:
- + writel(CTRL_LCD_DATABUS_WIDTH_24BIT,
- + host->base + LCDC_CTRL + REG_SET);
- + break;
- + }
- +
- + /* Configure the MPU timing */
- + writel((1 << TIMING_CMD_HOLD_OFFSET) | (1 << TIMING_CMD_SETUP_OFFSET) |
- + (1 << TIMING_DATA_HOLD_OFFSET) | (1 << TIMING_DATA_SETUP_OFFSET),
- + host->base + LCDC_TIMING);
- +
- + msleep(10);
- +}
- +
- static irqreturn_t mxsfb_irq_handler(int irq, void *dev_id)
- {
- struct mxsfb_info *host = dev_id;
- @@ -625,6 +752,11 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
- rgb = def_rgb565;
- break;
- case 32:
- + if (host->is_mpu_lcd) {
- + rgb = def_rgb888;
- + break;
- + }
- +
- switch (host->ld_intf_width) {
- case STMLCDIF_8BIT:
- pr_debug("Unsupported LCD bus width mapping\n");
- @@ -727,22 +859,24 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
- }
- clk_enable_pix(host);
- - writel(CTRL2_OUTSTANDING_REQS__REQ_16,
- - host->base + LCDC_V4_CTRL2 + REG_SET);
- + if (!host->is_mpu_lcd) {
- + writel(CTRL2_OUTSTANDING_REQS_REQ_16,
- + host->base + LCDC_V4_CTRL2 + REG_SET);
- - /* if it was disabled, re-enable the mode again */
- - writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
- + /* if it was disabled, re-enable the mode again */
- + writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
- - /* enable the SYNC signals first, then the DMA engine */
- - reg = readl(host->base + LCDC_VDCTRL4);
- - reg |= VDCTRL4_SYNC_SIGNALS_ON;
- - writel(reg, host->base + LCDC_VDCTRL4);
- + /* enable the SYNC signals first, then the DMA engine */
- + reg = readl(host->base + LCDC_VDCTRL4);
- + reg |= VDCTRL4_SYNC_SIGNALS_ON;
- + writel(reg, host->base + LCDC_VDCTRL4);
- - writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_SET);
- - writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
- + writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_SET);
- + writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
- - /* Recovery on underflow */
- - writel(CTRL1_RECOVERY_ON_UNDERFLOW, host->base + LCDC_CTRL1 + REG_SET);
- + /* Recovery on underflow */
- + writel(CTRL1_RECOVERY_ON_UNDERFLOW, host->base + LCDC_CTRL1 + REG_SET);
- + }
- host->enabled = 1;
- @@ -851,107 +985,122 @@ static int mxsfb_set_par(struct fb_info *fb_info)
- * This may lead into shifted pictures (FIFO issue?).
- * So, first stop the controller and drain its FIFOs
- */
- - if (host->enabled) {
- + if (host->enabled && (!host->is_mpu_lcd)) {
- reenable = 1;
- mxsfb_disable_controller(fb_info);
- }
- - /* clear the FIFOs */
- - writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
- -
- - ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
- - CTRL_SET_BUS_WIDTH(host->ld_intf_width);
- -
- - switch (fb_info->var.bits_per_pixel) {
- - case 16:
- - dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n");
- - ctrl |= CTRL_SET_WORD_LENGTH(0);
- - writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1);
- - break;
- - case 32:
- - dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
- - ctrl |= CTRL_SET_WORD_LENGTH(3);
- - switch (host->ld_intf_width) {
- - case STMLCDIF_8BIT:
- - dev_dbg(&host->pdev->dev,
- - "Unsupported LCD bus width mapping\n");
- - return -EINVAL;
- - case STMLCDIF_16BIT:
- - /* 24 bit to 18 bit mapping */
- - ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
- - * each colour component
- - */
- + if (host->is_mpu_lcd) {
- + if (host->enabled) {
- + mxsfb_mpu_setup_interface(host);
- + writel(fb_info->fix.smem_start +
- + fb_info->fix.line_length * fb_info->var.yoffset,
- + host->base + host->devdata->cur_buf);
- + writel(fb_info->fix.smem_start +
- + fb_info->fix.line_length * fb_info->var.yoffset,
- + host->base + host->devdata->next_buf);
- + host->mpu_lcd_functions->mpu_lcd_setup(host);
- + mxsfb_mpu_setup_refresh_data(host);
- + mxsfb_mpu_refresh_panel(host);
- + }
- + } else {
- + /* clear the FIFOs */
- + writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
- +
- + ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
- + CTRL_SET_BUS_WIDTH(host->ld_intf_width);
- +
- + switch (fb_info->var.bits_per_pixel) {
- + case 16:
- + dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n");
- + ctrl |= CTRL_SET_WORD_LENGTH(0);
- + writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1);
- break;
- - case STMLCDIF_18BIT:
- - if (pixfmt_is_equal(&fb_info->var, def_rgb666))
- + case 32:
- + dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
- + ctrl |= CTRL_SET_WORD_LENGTH(3);
- + switch (host->ld_intf_width) {
- + case STMLCDIF_8BIT:
- + dev_dbg(&host->pdev->dev,
- + "Unsupported LCD bus width mapping\n");
- + return -EINVAL;
- + case STMLCDIF_16BIT:
- /* 24 bit to 18 bit mapping */
- - ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
- - * each colour component
- - */
- - break;
- - case STMLCDIF_24BIT:
- - /* real 24 bit */
- + ctrl |= CTRL_DATA_FORMAT_24_BIT; /* ignore the upper 2 bits in
- + * each colour component
- + */
- + break;
- + case STMLCDIF_18BIT:
- + if (pixfmt_is_equal(&fb_info->var, def_rgb666))
- + /* 24 bit to 18 bit mapping */
- + ctrl |= CTRL_DATA_FORMAT_24_BIT; /* ignore the upper 2 bits in
- + * each colour component
- + */
- + break;
- + case STMLCDIF_24BIT:
- + /* real 24 bit */
- + break;
- + }
- + /* do not use packed pixels = one pixel per word instead */
- + writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
- break;
- + default:
- + dev_dbg(&host->pdev->dev, "Unhandled color depth of %u\n",
- + fb_info->var.bits_per_pixel);
- + return -EINVAL;
- }
- - /* do not use packed pixels = one pixel per word instead */
- - writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
- - break;
- - default:
- - dev_dbg(&host->pdev->dev, "Unhandled color depth of %u\n",
- - fb_info->var.bits_per_pixel);
- - return -EINVAL;
- - }
- - writel(ctrl, host->base + LCDC_CTRL);
- -
- - writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
- - TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
- - host->base + host->devdata->transfer_count);
- -
- - vdctrl0 = VDCTRL0_ENABLE_PRESENT | /* always in DOTCLOCK mode */
- - VDCTRL0_VSYNC_PERIOD_UNIT |
- - VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
- - VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
- - /* use the saved sync to avoid wrong sync information */
- - if (host->sync & FB_SYNC_HOR_HIGH_ACT)
- - vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
- - if (host->sync & FB_SYNC_VERT_HIGH_ACT)
- - vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
- - if (!(host->sync & FB_SYNC_OE_LOW_ACT))
- - vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
- - if (host->sync & FB_SYNC_CLK_LAT_FALL)
- - vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
- -
- - writel(vdctrl0, host->base + LCDC_VDCTRL0);
- -
- - /* frame length in lines */
- - writel(fb_info->var.upper_margin + fb_info->var.vsync_len +
- - fb_info->var.lower_margin + fb_info->var.yres,
- - host->base + LCDC_VDCTRL1);
- -
- - /* line length in units of clocks or pixels */
- - writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) |
- - VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin +
- - fb_info->var.hsync_len + fb_info->var.right_margin +
- - fb_info->var.xres),
- - host->base + LCDC_VDCTRL2);
- -
- - writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin +
- - fb_info->var.hsync_len) |
- - SET_VERT_WAIT_CNT(fb_info->var.upper_margin +
- - fb_info->var.vsync_len),
- - host->base + LCDC_VDCTRL3);
- -
- - vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres);
- - if (mxsfb_is_v4(host))
- - vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay);
- - writel(vdctrl4, host->base + LCDC_VDCTRL4);
- -
- - writel(fb_info->fix.smem_start +
- - fb_info->fix.line_length * fb_info->var.yoffset,
- - host->base + host->devdata->next_buf);
- -
- - if (reenable)
- + writel(ctrl, host->base + LCDC_CTRL);
- +
- + writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
- + TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
- + host->base + host->devdata->transfer_count);
- +
- + vdctrl0 = VDCTRL0_ENABLE_PRESENT | /* always in DOTCLOCK mode */
- + VDCTRL0_VSYNC_PERIOD_UNIT |
- + VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
- + VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
- + /* use the saved sync to avoid wrong sync information */
- + if (host->sync & FB_SYNC_HOR_HIGH_ACT)
- + vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
- + if (host->sync & FB_SYNC_VERT_HIGH_ACT)
- + vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
- + if (!(host->sync & FB_SYNC_OE_LOW_ACT))
- + vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
- + if (host->sync & FB_SYNC_CLK_LAT_FALL)
- + vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
- +
- + writel(vdctrl0, host->base + LCDC_VDCTRL0);
- +
- + /* frame length in lines */
- + writel(fb_info->var.upper_margin + fb_info->var.vsync_len +
- + fb_info->var.lower_margin + fb_info->var.yres,
- + host->base + LCDC_VDCTRL1);
- +
- + /* line length in units of clocks or pixels */
- + writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) |
- + VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin +
- + fb_info->var.hsync_len + fb_info->var.right_margin +
- + fb_info->var.xres),
- + host->base + LCDC_VDCTRL2);
- +
- + writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin +
- + fb_info->var.hsync_len) |
- + SET_VERT_WAIT_CNT(fb_info->var.upper_margin +
- + fb_info->var.vsync_len),
- + host->base + LCDC_VDCTRL3);
- +
- + vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres);
- + if (mxsfb_is_v4(host))
- + vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay);
- + writel(vdctrl4, host->base + LCDC_VDCTRL4);
- +
- + writel(fb_info->fix.smem_start +
- + fb_info->fix.line_length * fb_info->var.yoffset,
- + host->base + host->devdata->next_buf);
- + }
- +
- + if (reenable && (!host->is_mpu_lcd))
- mxsfb_enable_controller(fb_info);
- /* Clear activate as not Reconfiguring framebuffer again */
- @@ -1014,20 +1163,25 @@ static int mxsfb_wait_for_vsync(struct fb_info *fb_info)
- return -EINVAL;
- }
- - init_completion(&host->vsync_complete);
- + if (host->is_mpu_lcd) {
- + if (mxsfb_mpu_wait_for_ready(host) != 0)
- + return -ETIME;
- + } else {
- + init_completion(&host->vsync_complete);
- - host->wait4vsync = 1;
- - writel(CTRL1_VSYNC_EDGE_IRQ_EN,
- - host->base + LCDC_CTRL1 + REG_SET);
- - ret = wait_for_completion_interruptible_timeout(
- - &host->vsync_complete, 1 * HZ);
- - if (ret == 0) {
- - dev_err(fb_info->device,
- - "mxs wait for vsync timeout\n");
- - host->wait4vsync = 0;
- - ret = -ETIME;
- - } else if (ret > 0) {
- - ret = 0;
- + host->wait4vsync = 1;
- + writel(CTRL1_VSYNC_EDGE_IRQ_EN,
- + host->base + LCDC_CTRL1 + REG_SET);
- + ret = wait_for_completion_interruptible_timeout(
- + &host->vsync_complete, 1 * HZ);
- + if (ret == 0) {
- + dev_err(fb_info->device,
- + "mxs wait for vsync timeout\n");
- + host->wait4vsync = 0;
- + ret = -ETIME;
- + } else if (ret > 0) {
- + ret = 0;
- + }
- }
- return ret;
- }
- @@ -1035,12 +1189,16 @@ static int mxsfb_wait_for_vsync(struct fb_info *fb_info)
- static int mxsfb_ioctl(struct fb_info *fb_info, unsigned int cmd,
- unsigned long arg)
- {
- + struct mxsfb_info *host = fb_info->par;
- int ret = -EINVAL;
- switch (cmd) {
- case MXCFB_WAIT_FOR_VSYNC:
- ret = mxsfb_wait_for_vsync(fb_info);
- break;
- + case MXCFB_MPU_REFRESH_PANEL:
- + ret = mxsfb_mpu_refresh_panel(host);
- + break;
- default:
- break;
- }
- @@ -1059,6 +1217,8 @@ static int mxsfb_blank(int blank, struct fb_info *fb_info)
- case FB_BLANK_HSYNC_SUSPEND:
- case FB_BLANK_NORMAL:
- if (host->enabled) {
- + if (host->is_mpu_lcd)
- + host->mpu_lcd_functions->mpu_lcd_poweroff(host);
- mxsfb_disable_controller(fb_info);
- pm_runtime_put_sync_suspend(&host->pdev->dev);
- }
- @@ -1080,8 +1240,13 @@ static int mxsfb_blank(int blank, struct fb_info *fb_info)
- pm_runtime_get_sync(&host->pdev->dev);
- writel(0, host->base + LCDC_CTRL);
- - mxsfb_set_par(host->fb_info);
- - mxsfb_enable_controller(fb_info);
- + if (host->is_mpu_lcd) {
- + mxsfb_enable_controller(fb_info);
- + mxsfb_set_par(host->fb_info);
- + } else {
- + mxsfb_set_par(host->fb_info);
- + mxsfb_enable_controller(fb_info);
- + }
- }
- break;
- }
- @@ -1111,24 +1276,37 @@ static int mxsfb_pan_display(struct fb_var_screeninfo *var,
- return -EINVAL;
- }
- - init_completion(&host->flip_complete);
- + if (host->is_mpu_lcd) {
- + if (mxsfb_mpu_wait_for_ready(host) != 0)
- + return -ETIMEDOUT;
- - offset = fb_info->fix.line_length * var->yoffset;
- + offset = fb_info->fix.line_length * var->yoffset;
- - /* update on next VSYNC */
- - writel(fb_info->fix.smem_start + offset,
- - host->base + host->devdata->next_buf);
- + writel(fb_info->fix.smem_start + offset,
- + host->base + host->devdata->next_buf);
- + writel(fb_info->fix.smem_start + offset,
- + host->base + host->devdata->cur_buf);
- - writel(CTRL1_CUR_FRAME_DONE_IRQ_EN,
- - host->base + LCDC_CTRL1 + REG_SET);
- + mxsfb_mpu_refresh_panel(host);
- + } else {
- + init_completion(&host->flip_complete);
- - ret = wait_for_completion_timeout(&host->flip_complete, HZ / 2);
- - if (!ret) {
- - dev_err(fb_info->device,
- - "mxs wait for pan flip timeout\n");
- - return -ETIMEDOUT;
- - }
- + offset = fb_info->fix.line_length * var->yoffset;
- +
- + /* update on next VSYNC */
- + writel(fb_info->fix.smem_start + offset,
- + host->base + host->devdata->next_buf);
- +
- + writel(CTRL1_CUR_FRAME_DONE_IRQ_EN,
- + host->base + LCDC_CTRL1 + REG_SET);
- + ret = wait_for_completion_timeout(&host->flip_complete, HZ / 2);
- + if (!ret) {
- + dev_err(fb_info->device,
- + "mxs wait for pan flip timeout\n");
- + return -ETIMEDOUT;
- + }
- + }
- return 0;
- }
- @@ -1194,86 +1372,88 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
- */
- clk_enable_pix(host);
- - /* Only restore the mode when the controller is running */
- - ctrl = readl(host->base + LCDC_CTRL);
- - if (!(ctrl & CTRL_RUN))
- - return -EINVAL;
- + if (! host->is_mpu_lcd) {
- + /* Only restore the mode when the controller is running */
- + ctrl = readl(host->base + LCDC_CTRL);
- + if (!(ctrl & CTRL_RUN))
- + return -EINVAL;
- - memset(&vmode, 0, sizeof(vmode));
- + memset(&vmode, 0, sizeof(vmode));
- - vdctrl0 = readl(host->base + LCDC_VDCTRL0);
- - vdctrl2 = readl(host->base + LCDC_VDCTRL2);
- - vdctrl3 = readl(host->base + LCDC_VDCTRL3);
- - vdctrl4 = readl(host->base + LCDC_VDCTRL4);
- + vdctrl0 = readl(host->base + LCDC_VDCTRL0);
- + vdctrl2 = readl(host->base + LCDC_VDCTRL2);
- + vdctrl3 = readl(host->base + LCDC_VDCTRL3);
- + vdctrl4 = readl(host->base + LCDC_VDCTRL4);
- - transfer_count = readl(host->base + host->devdata->transfer_count);
- + transfer_count = readl(host->base + host->devdata->transfer_count);
- - vmode.xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
- - vmode.yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
- + vmode.xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
- + vmode.yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
- - switch (CTRL_GET_WORD_LENGTH(ctrl)) {
- - case 0:
- - bits_per_pixel = 16;
- - break;
- - case 3:
- - bits_per_pixel = 32;
- - break;
- - case 1:
- - default:
- - return -EINVAL;
- - }
- + switch (CTRL_GET_WORD_LENGTH(ctrl)) {
- + case 0:
- + bits_per_pixel = 16;
- + break;
- + case 3:
- + bits_per_pixel = 32;
- + break;
- + case 1:
- + default:
- + return -EINVAL;
- + }
- - fb_info->var.bits_per_pixel = bits_per_pixel;
- + fb_info->var.bits_per_pixel = bits_per_pixel;
- - vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk_pix) / 1000U);
- - vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2);
- - vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len;
- - vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len -
- - vmode.left_margin - vmode.xres;
- - vmode.vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
- - period = readl(host->base + LCDC_VDCTRL1);
- - vmode.upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode.vsync_len;
- - vmode.lower_margin = period - vmode.vsync_len - vmode.upper_margin - vmode.yres;
- + vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk_pix) / 1000U);
- + vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2);
- + vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len;
- + vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len -
- + vmode.left_margin - vmode.xres;
- + vmode.vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
- + period = readl(host->base + LCDC_VDCTRL1);
- + vmode.upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode.vsync_len;
- + vmode.lower_margin = period - vmode.vsync_len - vmode.upper_margin - vmode.yres;
- - vmode.vmode = FB_VMODE_NONINTERLACED;
- + vmode.vmode = FB_VMODE_NONINTERLACED;
- - vmode.sync = 0;
- - if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
- - vmode.sync |= FB_SYNC_HOR_HIGH_ACT;
- - if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
- - vmode.sync |= FB_SYNC_VERT_HIGH_ACT;
- + vmode.sync = 0;
- + if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
- + vmode.sync |= FB_SYNC_HOR_HIGH_ACT;
- + if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
- + vmode.sync |= FB_SYNC_VERT_HIGH_ACT;
- - pr_debug("Reconstructed video mode:\n");
- - pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
- - vmode.xres, vmode.yres,
- - vmode.hsync_len, vmode.left_margin, vmode.right_margin,
- - vmode.vsync_len, vmode.upper_margin, vmode.lower_margin);
- - pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode.pixclock));
- + pr_debug("Reconstructed video mode:\n");
- + pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
- + vmode.xres, vmode.yres,
- + vmode.hsync_len, vmode.left_margin, vmode.right_margin,
- + vmode.vsync_len, vmode.upper_margin, vmode.lower_margin);
- + pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode.pixclock));
- - fb_add_videomode(&vmode, &fb_info->modelist);
- + fb_add_videomode(&vmode, &fb_info->modelist);
- - host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
- - host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
- + host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
- + host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
- - fb_info->fix.line_length = vmode.xres * (bits_per_pixel >> 3);
- + fb_info->fix.line_length = vmode.xres * (bits_per_pixel >> 3);
- - pa = readl(host->base + host->devdata->cur_buf);
- - fbsize = fb_info->fix.line_length * vmode.yres;
- - if (pa < fb_info->fix.smem_start)
- - return -EINVAL;
- - if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
- - return -EINVAL;
- - ofs = pa - fb_info->fix.smem_start;
- - if (ofs) {
- - memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
- - writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
- - }
- + pa = readl(host->base + host->devdata->cur_buf);
- + fbsize = fb_info->fix.line_length * vmode.yres;
- + if (pa < fb_info->fix.smem_start)
- + return -EINVAL;
- + if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
- + return -EINVAL;
- + ofs = pa - fb_info->fix.smem_start;
- + if (ofs) {
- + memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
- + writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
- + }
- - line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
- - fb_info->fix.ypanstep = 1;
- - fb_info->fix.ywrapstep = 1;
- + line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
- + fb_info->fix.ypanstep = 1;
- + fb_info->fix.ywrapstep = 1;
- - host->enabled = 1;
- + host->enabled = 1;
- + }
- return 0;
- }
- @@ -1290,6 +1470,7 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
- const char *disp_dev, *disp_videomode;
- u32 width;
- int i;
- + const char *lcd_panel;
- int ret = 0;
- host->id = of_alias_get_id(np, "lcdif");
- @@ -1299,84 +1480,156 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
- dev_err(dev, "failed to find display phandle\n");
- return -ENOENT;
- }
- +
- + host->is_mpu_lcd = of_property_read_bool(display_np, "mpu-mode");
- + if (host->is_mpu_lcd) {
- + struct fb_videomode *mpu_lcd_modedb;
- + struct fb_videomode fb_vm;
- + int size;
- - ret = of_property_read_u32(display_np, "bus-width", &width);
- - if (ret < 0) {
- - dev_err(dev, "failed to get property bus-width\n");
- - goto put_display_node;
- - }
- + ret = of_property_read_string(display_np, "lcd_panel", &lcd_panel);
- + if (ret) {
- + dev_err(dev, "failed to read of property lcd_panel\n");
- + goto put_display_node;
- + }
- - switch (width) {
- - case 8:
- - host->ld_intf_width = STMLCDIF_8BIT;
- - break;
- - case 16:
- - host->ld_intf_width = STMLCDIF_16BIT;
- - break;
- - case 18:
- - host->ld_intf_width = STMLCDIF_18BIT;
- - break;
- - case 24:
- - host->ld_intf_width = STMLCDIF_24BIT;
- - break;
- - default:
- - dev_err(dev, "invalid bus-width value\n");
- - ret = -EINVAL;
- - goto put_display_node;
- - }
- + for (i = 0; i < ARRAY_SIZE(mpu_lcd_db); i++) {
- + if (!strcmp(lcd_panel, mpu_lcd_db[i].lcd_panel)) {
- + host->mpu_lcd_functions =
- + &mpu_lcd_db[i].lcd_callback;
- + break;
- + }
- + }
- + if (i == ARRAY_SIZE(mpu_lcd_db)) {
- + dev_err(dev, "failed to find supported lcd panel.\n");
- + ret = -EINVAL;
- + goto put_display_node;
- + }
- + host->mpu_lcd_functions->get_mpu_lcd_videomode(&mpu_lcd_modedb, &size,
- + &host->mpu_lcd_sigs);
- - ret = of_property_read_u32(display_np, "bits-per-pixel",
- - &var->bits_per_pixel);
- - if (ret < 0) {
- - dev_err(dev, "failed to get property bits-per-pixel\n");
- - goto put_display_node;
- - }
- + memcpy(&fb_vm, mpu_lcd_modedb, sizeof(struct fb_videomode));
- + var->bits_per_pixel = host->mpu_lcd_sigs->panel_bpp;
- - ret = of_property_read_string(np, "disp-dev", &disp_dev);
- - if (!ret) {
- - memcpy(host->disp_dev, disp_dev, strlen(disp_dev));
- + switch (host->mpu_lcd_sigs->interface_width) {
- + case 8:
- + host->ld_intf_width = STMLCDIF_8BIT;
- + break;
- + case 16:
- + host->ld_intf_width = STMLCDIF_16BIT;
- + break;
- + case 18:
- + host->ld_intf_width = STMLCDIF_18BIT;
- + break;
- + case 24:
- + host->ld_intf_width = STMLCDIF_24BIT;
- + break;
- + default:
- + dev_err(dev, "invalid interface width value\n");
- + ret = -EINVAL;
- + goto put_display_node;
- + }
- - if (!of_property_read_string(np, "disp-videomode",
- - &disp_videomode)) {
- - memcpy(host->disp_videomode, disp_videomode,
- - strlen(disp_videomode));
- + /* lcd reset gpio pin */
- + host->mpu_lcd_sigs->lcd_reset_is_gpio = 0;
- + host->mpu_lcd_sigs->lcd_reset_gpio = of_get_named_gpio(display_np, "lcd_reset_gpio", 0);
- + if (gpio_is_valid(host->mpu_lcd_sigs->lcd_reset_gpio)) {
- + dev_info(dev, "find lcd reset gpio pin.\n");
- + if (devm_gpio_request_one(dev, host->mpu_lcd_sigs->lcd_reset_gpio, GPIOF_OUT_INIT_HIGH, "lcd_reset") >= 0)
- + host->mpu_lcd_sigs->lcd_reset_is_gpio = 1;
- }
- - /* Timing is from encoder driver */
- - goto put_display_node;
- - }
- + /* lcd rs gpio pin */
- + host->mpu_lcd_sigs->lcd_rs_is_gpio = 0;
- + host->mpu_lcd_sigs->lcd_rs_gpio = of_get_named_gpio(display_np, "lcd_rs_gpio", 0);
- + if (gpio_is_valid(host->mpu_lcd_sigs->lcd_rs_gpio)) {
- + dev_info(dev, "find lcd rs gpio pin.\n");
- + if (devm_gpio_request_one(dev, host->mpu_lcd_sigs->lcd_rs_is_gpio, GPIOF_OUT_INIT_HIGH, "lcd_rs") >= 0)
- + host->mpu_lcd_sigs->lcd_rs_is_gpio = 1;
- + }
- - timings = of_get_display_timings(display_np);
- - if (!timings) {
- - dev_err(dev, "failed to get display timings\n");
- - ret = -ENOENT;
- - goto put_display_node;
- - }
- + fb_add_videomode(&fb_vm, &fb_info->modelist);
- + goto put_display_node;
- + } else {
- - timings_np = of_find_node_by_name(display_np,
- - "display-timings");
- - if (!timings_np) {
- - dev_err(dev, "failed to find display-timings node\n");
- - ret = -ENOENT;
- - goto put_display_node;
- - }
- + ret = of_property_read_u32(display_np, "bus-width", &width);
- + if (ret < 0) {
- + dev_err(dev, "failed to get property bus-width\n");
- + goto put_display_node;
- + }
- - for (i = 0; i < of_get_child_count(timings_np); i++) {
- - struct videomode vm;
- - struct fb_videomode fb_vm;
- + switch (width) {
- + case 8:
- + host->ld_intf_width = STMLCDIF_8BIT;
- + break;
- + case 16:
- + host->ld_intf_width = STMLCDIF_16BIT;
- + break;
- + case 18:
- + host->ld_intf_width = STMLCDIF_18BIT;
- + break;
- + case 24:
- + host->ld_intf_width = STMLCDIF_24BIT;
- + break;
- + default:
- + dev_err(dev, "invalid bus-width value\n");
- + ret = -EINVAL;
- + goto put_display_node;
- + }
- - ret = videomode_from_timings(timings, &vm, i);
- - if (ret < 0)
- - goto put_timings_node;
- - ret = fb_videomode_from_videomode(&vm, &fb_vm);
- - if (ret < 0)
- - goto put_timings_node;
- + ret = of_property_read_u32(display_np, "bits-per-pixel",
- + &var->bits_per_pixel);
- + if (ret < 0) {
- + dev_err(dev, "failed to get property bits-per-pixel\n");
- + goto put_display_node;
- + }
- - if (!(vm.flags & DISPLAY_FLAGS_DE_HIGH))
- - fb_vm.sync |= FB_SYNC_OE_LOW_ACT;
- - if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
- - fb_vm.sync |= FB_SYNC_CLK_LAT_FALL;
- - fb_add_videomode(&fb_vm, &fb_info->modelist);
- + ret = of_property_read_string(np, "disp-dev", &disp_dev);
- + if (!ret) {
- + memcpy(host->disp_dev, disp_dev, strlen(disp_dev));
- +
- + if (!of_property_read_string(np, "disp-videomode",
- + &disp_videomode)) {
- + memcpy(host->disp_videomode, disp_videomode,
- + strlen(disp_videomode));
- + }
- +
- + /* Timing is from encoder driver */
- + goto put_display_node;
- + }
- +
- + timings = of_get_display_timings(display_np);
- + if (!timings) {
- + dev_err(dev, "failed to get display timings\n");
- + ret = -ENOENT;
- + goto put_display_node;
- + }
- +
- + timings_np = of_find_node_by_name(display_np,
- + "display-timings");
- + if (!timings_np) {
- + dev_err(dev, "failed to find display-timings node\n");
- + ret = -ENOENT;
- + goto put_display_node;
- + }
- +
- + for (i = 0; i < of_get_child_count(timings_np); i++) {
- + struct videomode vm;
- + struct fb_videomode fb_vm;
- +
- + ret = videomode_from_timings(timings, &vm, i);
- + if (ret < 0)
- + goto put_timings_node;
- + ret = fb_videomode_from_videomode(&vm, &fb_vm);
- + if (ret < 0)
- + goto put_timings_node;
- +
- + if (!(vm.flags & DISPLAY_FLAGS_DE_HIGH))
- + fb_vm.sync |= FB_SYNC_OE_LOW_ACT;
- + if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
- + fb_vm.sync |= FB_SYNC_CLK_LAT_FALL;
- + fb_add_videomode(&fb_vm, &fb_info->modelist);
- + }
- }
- put_timings_node:
- @@ -2309,8 +2562,13 @@ static int mxsfb_probe(struct platform_device *pdev)
- if (!host->enabled) {
- writel(0, host->base + LCDC_CTRL);
- - mxsfb_set_par(fb_info);
- - mxsfb_enable_controller(fb_info);
- + if (host->is_mpu_lcd) {
- + mxsfb_enable_controller(fb_info);
- + mxsfb_set_par(host->fb_info);
- + } else {
- + mxsfb_set_par(host->fb_info);
- + mxsfb_enable_controller(fb_info);
- + }
- pm_runtime_get_sync(&host->pdev->dev);
- }
- @@ -2388,6 +2646,8 @@ static void mxsfb_shutdown(struct platform_device *pdev)
- if (host->cur_blank == FB_BLANK_UNBLANK) {
- writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
- writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_CLR);
- + if (host->is_mpu_lcd)
- + host->mpu_lcd_functions->mpu_lcd_poweroff(host);
- }
- }
- @@ -2447,7 +2707,9 @@ static int mxsfb_resume(struct device *pdev)
- struct mxsfb_info *host = dev_get_drvdata(pdev);
- struct fb_info *fb_info = host->fb_info;
- - pinctrl_pm_select_default_state(pdev);
- + // TODO: Watch this, this looks like an infinite recursive loop...
- + // - pinctrl_pm_select_default_state(pdev);
- + mxsfb_resume(pdev);
- console_lock();
- mxsfb_blank(host->restore_blank, fb_info);
- diff --git a/drivers/video/fbdev/mxsfb.h b/drivers/video/fbdev/mxsfb.h
- new file mode 100644
- index 000000000000..822d4ebb9cc9
- --- /dev/null
- +++ b/drivers/video/fbdev/mxsfb.h
- @@ -0,0 +1,371 @@
- +/*
- +* Copyright (C) 2016 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 __MXSFB_H__
- +#define __MXSFB_H__
- +
- +#include <linux/regmap.h>
- +#include <linux/platform_device.h>
- +#include <linux/fb.h>
- +#include <linux/mxcfb.h>
- +#include <linux/pm_qos.h>
- +
- +#define REG_SET 4
- +#define REG_CLR 8
- +
- +#define LCDC_CTRL 0x00
- +#define LCDC_CTRL1 0x10
- +#define LCDC_V4_CTRL2 0x20
- +#define LCDC_V3_TRANSFER_COUNT 0x20
- +#define LCDC_V4_TRANSFER_COUNT 0x30
- +#define LCDC_V4_CUR_BUF 0x40
- +#define LCDC_V4_NEXT_BUF 0x50
- +#define LCDC_V3_CUR_BUF 0x30
- +#define LCDC_V3_NEXT_BUF 0x40
- +#define LCDC_TIMING 0x60
- +#define LCDC_VDCTRL0 0x70
- +#define LCDC_VDCTRL1 0x80
- +#define LCDC_VDCTRL2 0x90
- +#define LCDC_VDCTRL3 0xa0
- +#define LCDC_VDCTRL4 0xb0
- +#define LCDC_DVICTRL0 0xc0
- +#define LCDC_DVICTRL1 0xd0
- +#define LCDC_DVICTRL2 0xe0
- +#define LCDC_DVICTRL3 0xf0
- +#define LCDC_DVICTRL4 0x100
- +#define LCDC_V4_DATA 0x180
- +#define LCDC_V3_DATA 0x1b0
- +#define LCDC_V4_DEBUG0 0x1d0
- +#define LCDC_V3_DEBUG0 0x1f0
- +#define LCDC_AS_CTRL 0x210
- +#define LCDC_AS_BUF 0x220
- +#define LCDC_AS_NEXT_BUF 0x230
- +
- +#define CTRL_SFTRST (1 << 31)
- +#define CTRL_CLKGATE (1 << 30)
- +#define CTRL_YCBCR422_INPUT (1 << 29)
- +#define CTRL_READ_WRITEB (1 << 28)
- +#define CTRL_WAIT_FOR_VSYNC_EDGE (1 << 27)
- +#define CTRL_DATA_SHIFT_DIR (1 << 26)
- +#define CTRL_SHIFT_NUM_BITS_MASK (0x1f << 21)
- +#define CTRL_SHIFT_NUM_BITS_OFFSET 21
- +#define CTRL_DVI_MODE (1 << 20)
- +#define CTRL_BYPASS_COUNT (1 << 19)
- +#define CTRL_VSYNC_MODE (1 << 18)
- +#define CTRL_DOTCLK_MODE (1 << 17)
- +#define CTRL_DATA_SELECT (1 << 16)
- +#define CTRL_INPUT_DATA_SWIZZLE_MASK (0x3 << 14)
- +#define CTRL_INPUT_DATA_SWIZZLE_OFFSET 14
- +#define CTRL_CSC_DATA_SWIZZLE_MASK (0x3 << 12)
- +#define CTRL_CSC_DATA_SWIZZLE_OFFSET 12
- +#define CTRL_LCD_DATABUS_WIDTH_MASK (0x3 << 10)
- +#define CTRL_LCD_DATABUS_WIDTH_OFFSET 10
- +#define CTRL_LCD_DATABUS_WIDTH_16BIT (0 << 10)
- +#define CTRL_LCD_DATABUS_WIDTH_8BIT (1 << 10)
- +#define CTRL_LCD_DATABUS_WIDTH_18BIT (2 << 10)
- +#define CTRL_LCD_DATABUS_WIDTH_24BIT (3 << 10)
- +#define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10)
- +#define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3)
- +#define CTRL_WORD_LENGTH_MASK (0x3 << 8)
- +#define CTRL_WORD_LENGTH_OFFSET 8
- +#define CTRL_WORD_LENGTH_16BIT (0 << 8)
- +#define CTRL_WORD_LENGTH_8BIT (1 << 8)
- +#define CTRL_WORD_LENGTH_18BIT (2 << 8)
- +#define CTRL_WORD_LENGTH_24BIT (3 << 8)
- +#define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8)
- +#define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3)
- +#define CTRL_RGB_TO_YCBCR422_CSC (1 << 7)
- +#define CTRL_MASTER (1 << 5)
- +#define CTRL_DATA_FORMAT_16_BIT (1 << 3)
- +#define CTRL_DATA_FORMAT_18_BIT (1 << 2)
- +#define CTRL_DATA_FORMAT_24_BIT (1 << 1)
- +#define CTRL_RUN (1 << 0)
- +
- +#define CTRL1_COMBINE_MPU_WR_STRB (1 << 27)
- +#define CTRL1_BM_ERROR_IRQ_EN (1 << 26)
- +#define CTRL1_BM_ERROR_IRQ (1 << 25)
- +#define CTRL1_RECOVERY_ON_UNDERFLOW (1 << 24)
- +#define CTRL1_INTERLACE_FIELDS (1 << 23)
- +#define CTRL1_START_INTERLACE_FROM_SECOND_FIELD (1 << 22)
- +#define CTRL1_FIFO_CLEAR (1 << 21)
- +#define CTRL1_IRQ_ON_ALTERNATE_FIELDS (1 << 20)
- +#define CTRL1_BYTE_PACKING_FORMAT_MASK (0xf << 16)
- +#define CTRL1_BYTE_PACKING_FORMAT_OFFSET 16
- +#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
- +#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
- +#define CTRL1_OVERFLOW_IRQ_EN (1 << 15)
- +#define CTRL1_UNDERFLOW_IRQ_EN (1 << 14)
- +#define CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13)
- +#define CTRL1_VSYNC_EDGE_IRQ_EN (1 << 12)
- +#define CTRL1_OVERFLOW_IRQ (1 << 11)
- +#define CTRL1_UNDERFLOW_IRQ (1 << 10)
- +#define CTRL1_CUR_FRAME_DONE_IRQ (1 << 9)
- +#define CTRL1_VSYNC_EDGE_IRQ (1 << 8)
- +#define CTRL1_BUSY_ENABLE (1 << 2)
- +#define CTRL1_MODE86 (1 << 1)
- +#define CTRL1_RESET (1 << 0)
- +#define CTRL1_IRQ_ENABLE_MASK (CTRL1_OVERFLOW_IRQ_EN | \
- + CTRL1_UNDERFLOW_IRQ_EN | \
- + CTRL1_CUR_FRAME_DONE_IRQ_EN | \
- + CTRL1_VSYNC_EDGE_IRQ_EN)
- +#define CTRL1_IRQ_ENABLE_SHIFT 12
- +#define CTRL1_IRQ_STATUS_MASK (CTRL1_OVERFLOW_IRQ | \
- + CTRL1_UNDERFLOW_IRQ | \
- + CTRL1_CUR_FRAME_DONE_IRQ | \
- + CTRL1_VSYNC_EDGE_IRQ)
- +#define CTRL1_IRQ_STATUS_SHIFT 8
- +
- +#define CTRL2_OUTSTANDING_REQS_MASK (0x7 << 21)
- +#define CTRL2_OUTSTANDING_REQS_OFFSET 21
- +#define CTRL2_OUTSTANDING_REQS_REQ_1 (0x0 << 21)
- +#define CTRL2_OUTSTANDING_REQS_REQ_2 (0x1 << 21)
- +#define CTRL2_OUTSTANDING_REQS_REQ_4 (0x2 << 21)
- +#define CTRL2_OUTSTANDING_REQS_REQ_8 (0x3 << 21)
- +#define CTRL2_OUTSTANDING_REQS_REQ_16 (0x4 << 21)
- +#define CTRL2_BURST_LEN_8 (1 << 20)
- +#define CTRL2_ODD_LINE_PATTERN_MASK (0x7 << 16)
- +#define CTRL2_ODD_LINE_PATTERN_OFFSET 16
- +#define CTRL2_ODD_LINE_PATTERN_RGB (0x0 << 16)
- +#define CTRL2_ODD_LINE_PATTERN_RBG (0x1 << 16)
- +#define CTRL2_ODD_LINE_PATTERN_GBR (0x2 << 16)
- +#define CTRL2_ODD_LINE_PATTERN_GRB (0x3 << 16)
- +#define CTRL2_ODD_LINE_PATTERN_BRG (0x4 << 16)
- +#define CTRL2_ODD_LINE_PATTERN_BGR (0x5 << 16)
- +#define CTRL2_EVEN_LINE_PATTERN_MASK (0x7 << 12)
- +#define CTRL2_EVEN_LINE_PATTERN_OFFSET 12
- +#define CTRL2_EVEN_LINE_PATTERN_RGB (0x0 << 12)
- +#define CTRL2_EVEN_LINE_PATTERN_RBG (0x1 << 12)
- +#define CTRL2_EVEN_LINE_PATTERN_GBR (0x2 << 12)
- +#define CTRL2_EVEN_LINE_PATTERN_GRB (0x3 << 12)
- +#define CTRL2_EVEN_LINE_PATTERN_BRG (0x4 << 12)
- +#define CTRL2_EVEN_LINE_PATTERN_BGR (0x5 << 12)
- +#define CTRL2_READ_PACK_DIR (1 << 10)
- +#define CTRL2_READ_MODE_OUTPUT_IN_RGB_FORMAT (1 << 9)
- +#define CTRL2_READ_MODE_6_BIT_INPUT (1 << 8)
- +#define CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_MASK (0x7 << 4)
- +#define CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_OFFSET 4
- +#define CTRL2_INITIAL_DUMMY_READ_MASK (0x7 << 1)
- +#define CTRL2_INITIAL_DUMMY_READ_OFFSET 1
- +
- +#define TRANSFER_COUNT_V_COUNT_MASK (0xffff << 16)
- +#define TRANSFER_COUNT_V_COUNT_OFFSET 16
- +#define TRANSFER_COUNT_H_COUNT_MASK (0xffff << 0)
- +#define TRANSFER_COUNT_H_COUNT_OFFSET 0
- +#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
- +#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
- +#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)
- +#define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff)
- +
- +#define CUR_BUF_ADDR_MASK 0xffffffff
- +#define CUR_BUF_ADDR_OFFSET 0
- +
- +#define NEXT_BUF_ADDR_MASK 0xffffffff
- +#define NEXT_BUF_ADDR_OFFSET 0
- +
- +#define TIMING_CMD_HOLD_MASK (0xff << 24)
- +#define TIMING_CMD_HOLD_OFFSET 24
- +#define TIMING_CMD_SETUP_MASK (0xff << 16)
- +#define TIMING_CMD_SETUP_OFFSET 16
- +#define TIMING_DATA_HOLD_MASK (0xff << 8)
- +#define TIMING_DATA_HOLD_OFFSET 8
- +#define TIMING_DATA_SETUP_MASK (0xff << 0)
- +#define TIMING_DATA_SETUP_OFFSET 0
- +
- +#define VDCTRL0_VSYNC_OEB (1 << 29)
- +#define VDCTRL0_ENABLE_PRESENT (1 << 28)
- +#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
- +#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
- +#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25)
- +#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24)
- +#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
- +#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
- +#define VDCTRL0_HALF_LINE (1 << 19)
- +#define VDCTRL0_HALF_LINE_MODE (1 << 18)
- +#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
- +#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
- +
- +#define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
- +#define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
- +
- +#define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29)
- +#define VDCTRL3_VSYNC_ONLY (1 << 28)
- +#define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16)
- +#define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff)
- +#define SET_VERT_WAIT_CNT(x) ((x) & 0xffff)
- +#define GET_VERT_WAIT_CNT(x) ((x) & 0xffff)
- +
- +#define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */
- +#define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */
- +#define VDCTRL4_SYNC_SIGNALS_ON (1 << 18)
- +#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
- +
- +#define DEBUG0_HSYNC (1 < 26)
- +#define DEBUG0_VSYNC (1 < 25)
- +
- +#define MIN_XRES 120
- +#define MIN_YRES 120
- +
- +#define RED 0
- +#define GREEN 1
- +#define BLUE 2
- +#define TRANSP 3
- +
- +#define STMLCDIF_8BIT 1 /** pixel data bus to the display is of 8 bit width */
- +#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
- +#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
- +#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
- +
- +#define FB_SYNC_OE_LOW_ACT 0x80000000
- +#define FB_SYNC_CLK_LAT_FALL 0x40000000
- +
- +enum mxsfb_devtype {
- + MXSFB_V3,
- + MXSFB_V4,
- + MXSFB_V5,
- +};
- +
- +enum {
- + MPU_DATA,
- + MPU_CMD,
- +};
- +
- +enum {
- + MPU_READ,
- + MPU_WRITE,
- +};
- +
- +enum {
- + MPU_BUS_8080,
- + MPU_BUS_6800,
- +};
- +
- +struct mpu_lcd_config {
- + u32 bus_mode;
- + u32 interface_width;
- + u32 panel_bpp;
- + bool lcd_reset_is_gpio;
- + int lcd_reset_gpio;
- + bool lcd_rs_is_gpio;
- + int lcd_rs_gpio;
- +};
- +
- +/* CPU dependent register offsets */
- +struct mxsfb_devdata {
- + unsigned transfer_count;
- + unsigned data;
- + unsigned cur_buf;
- + unsigned next_buf;
- + unsigned debug0;
- + unsigned hs_wdth_mask;
- + unsigned hs_wdth_shift;
- + unsigned ipversion;
- + u32 flags;
- +};
- +
- +struct mxsfb_layer;
- +
- +struct mxsfb_layer_ops {
- + void (*enable)(struct mxsfb_layer *ofb);
- + void (*disable)(struct mxsfb_layer *ofb);
- + void (*setup)(struct mxsfb_layer *ofb);
- +};
- +
- +struct mxsfb_layer {
- + struct fb_info *ol_fb;
- + int id;
- + int registered;
- + atomic_t usage;
- + int blank_state;
- + uint32_t global_alpha;
- +
- + struct mxsfb_layer_ops *ops;
- +
- + struct device *dev;
- + void __iomem *video_mem;
- + unsigned long video_mem_phys;
- + size_t video_mem_size;
- +
- + struct mxsfb_info *fbi;
- +};
- +
- +#define NAME_LEN 32
- +
- +struct mxsfb_info;
- +
- +struct mpu_lcd_callback {
- + /* callback for lcd panel operation */
- + void (*get_mpu_lcd_videomode)(struct fb_videomode **, int *,
- + struct mpu_lcd_config **);
- + int (*mpu_lcd_setup)(struct mxsfb_info *);
- + int (*mpu_lcd_poweroff)(struct mxsfb_info *);
- +};
- +
- +struct mpu_match_lcd {
- + char *lcd_panel;
- + struct mpu_lcd_callback lcd_callback;
- +};
- +
- +struct mxsfb_info {
- + struct fb_info *fb_info;
- + struct platform_device *pdev;
- + struct clk *clk_pix;
- + struct clk *clk_axi;
- + struct clk *clk_disp_axi;
- + bool clk_pix_enabled;
- + bool clk_axi_enabled;
- + bool clk_disp_axi_enabled;
- + void __iomem *base; /* registers */
- + u32 sync; /* record display timing polarities */
- + unsigned allocated_size;
- + int enabled;
- + unsigned ld_intf_width;
- + unsigned dotclk_delay;
- + const struct mxsfb_devdata *devdata;
- + struct regulator *reg_lcd;
- + bool wait4vsync;
- + struct completion vsync_complete;
- + struct completion flip_complete;
- + int cur_blank;
- + int restore_blank;
- + char disp_dev[NAME_LEN];
- + struct mxc_dispdrv_handle *dispdrv;
- + int id;
- + struct fb_var_screeninfo var;
- + struct pm_qos_request pm_qos_req;
- +
- + char disp_videomode[NAME_LEN];
- +
- + bool is_mpu_lcd;
- + struct mpu_lcd_config * mpu_lcd_sigs;
- + struct mpu_lcd_callback * mpu_lcd_functions;
- +
- +#ifdef CONFIG_FB_MXC_OVERLAY
- + struct mxsfb_layer overlay;
- +#endif
- +};
- +
- +unsigned int mxsfb_mpu_access(struct mxsfb_info *host, int mode, int rw, int data);
- +
- +#ifdef CONFIG_FB_MXS_ST7789S_QVGA
- +void mpu_st7789s_get_lcd_videomode(struct fb_videomode **mode, int *size,
- + struct mpu_lcd_config **data);
- +int mpu_st7789s_lcd_setup(struct mxsfb_info * mxsfb);
- +int mpu_st7789s_lcd_poweroff(struct mxsfb_info * mxsfb);
- +#endif
- +
- +#endif
- diff --git a/include/uapi/linux/mxcfb.h b/include/uapi/linux/mxcfb.h
- index 3a984090769a..c05b486c4dcb 100644
- --- a/include/uapi/linux/mxcfb.h
- +++ b/include/uapi/linux/mxcfb.h
- @@ -182,6 +182,9 @@ struct mxcfb_csc_matrix {
- #define MXCFB_SET_GPU_SPLIT_FMT _IOW('F', 0x2F, struct mxcfb_gpu_split_fmt)
- #define MXCFB_SET_PREFETCH _IOW('F', 0x30, int)
- #define MXCFB_GET_PREFETCH _IOR('F', 0x31, int)
- +
- +/* IOCTLs for mpu panel updates */
- +#define MXCFB_MPU_REFRESH_PANEL _IOW('F', 0x33, u_int32_t)
- /* IOCTLs for E-ink panel updates */
- #define MXCFB_SET_WAVEFORM_MODES _IOW('F', 0x2B, struct mxcfb_waveform_modes)
- --
- 2.19.1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement