Guest User

0001-Add-ST7789S-MPU-LCD-support-for-iMX6UL-board.patch

a guest
Nov 30th, 2018
308
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. From 8c186f7abd7fde6db432f2f4e91086e68906cbf7 Mon Sep 17 00:00:00 2001
  2. From: b19715 <b19715@freescale.com>
  3. Date: Wed, 17 Oct 2018 10:10:37 -0400
  4. Subject: [PATCH 03/11] Add ST7789S MPU LCD support for iMX6UL board
  5.  
  6. Updated for L4.9.11 release
  7. ---
  8. arch/arm/boot/dts/Makefile | 1 +
  9. arch/arm/boot/dts/imx6ul-14x14-evk-i80lcd.dts | 197 +++
  10. arch/arm/configs/imx_v7_defconfig | 1 +
  11. drivers/video/fbdev/mxc/Kconfig | 4 +
  12. drivers/video/fbdev/mxc/Makefile | 1 +
  13. drivers/video/fbdev/mxc/mxsfb_st7789s_qvga.c | 180 +++
  14. drivers/video/fbdev/mxsfb.c | 1196 ++++++++++-------
  15. drivers/video/fbdev/mxsfb.h | 371 +++++
  16. include/uapi/linux/mxcfb.h | 3 +
  17. 9 files changed, 1487 insertions(+), 467 deletions(-)
  18. create mode 100644 arch/arm/boot/dts/imx6ul-14x14-evk-i80lcd.dts
  19. create mode 100644 drivers/video/fbdev/mxc/mxsfb_st7789s_qvga.c
  20. create mode 100644 drivers/video/fbdev/mxsfb.h
  21.  
  22. diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
  23. index 5f9cf31dc0b8..4969795383df 100644
  24. --- a/arch/arm/boot/dts/Makefile
  25. +++ b/arch/arm/boot/dts/Makefile
  26. @@ -485,6 +485,7 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
  27. imx6ul-14x14-evk-btwifi.dtb \
  28. imx6ul-14x14-evk-btwifi-oob.dtb \
  29. imx6ul-14x14-evk-csi.dtb \
  30. + imx6ul-14x14-evk-i80lcd.dtb \
  31. imx6ul-14x14-evk-emmc.dtb \
  32. imx6ul-14x14-evk-gpmi-weim.dtb \
  33. imx6ul-14x14-evk-usb-certi.dtb \
  34. diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-i80lcd.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-i80lcd.dts
  35. new file mode 100644
  36. index 000000000000..9d7169877205
  37. --- /dev/null
  38. +++ b/arch/arm/boot/dts/imx6ul-14x14-evk-i80lcd.dts
  39. @@ -0,0 +1,197 @@
  40. +/*
  41. + * Copyright (C) 2015 Freescale Semiconductor, Inc.
  42. + *
  43. + * This program is free software; you can redistribute it and/or modify
  44. + * it under the terms of the GNU General Public License version 2 as
  45. + * published by the Free Software Foundation.
  46. + */
  47. +
  48. +/dts-v1/;
  49. +
  50. +#include <dt-bindings/input/input.h>
  51. +#include "imx6ul.dtsi"
  52. +
  53. +/ {
  54. + model = "Freescale i.MX6 UltraLite 14x14 EVK Board";
  55. + compatible = "fsl,imx6ul-14x14-evk", "fsl,imx6ul";
  56. +
  57. + chosen {
  58. + stdout-path = &uart1;
  59. + };
  60. +
  61. + memory {
  62. + reg = <0x80000000 0x20000000>;
  63. + };
  64. +
  65. + pxp_v4l2 {
  66. + compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
  67. + status = "okay";
  68. + };
  69. +
  70. + regulators {
  71. + compatible = "simple-bus";
  72. + #address-cells = <1>;
  73. + #size-cells = <0>;
  74. +
  75. + reg_sd1_vmmc: regulator@1 {
  76. + compatible = "regulator-fixed";
  77. + regulator-name = "VSD_3V3";
  78. + regulator-min-microvolt = <3300000>;
  79. + regulator-max-microvolt = <3300000>;
  80. + gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
  81. + enable-active-high;
  82. + };
  83. + };
  84. +};
  85. +
  86. +&cpu0 {
  87. + arm-supply = <&reg_arm>;
  88. + soc-supply = <&reg_soc>;
  89. +};
  90. +
  91. +&clks {
  92. + assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
  93. + assigned-clock-rates = <786432000>;
  94. +};
  95. +
  96. +&gpc {
  97. + fsl,cpu_pupscr_sw2iso = <0x1>;
  98. + fsl,cpu_pupscr_sw = <0x0>;
  99. + fsl,cpu_pdnscr_iso2sw = <0x1>;
  100. + fsl,cpu_pdnscr_iso = <0x1>;
  101. + fsl,wdog-reset = <1>; /* watchdog select of reset source */
  102. + fsl,ldo-bypass = <0>; /* DCDC, ldo-enable */
  103. +};
  104. +
  105. +&lcdif {
  106. + pinctrl-names = "default";
  107. + pinctrl-0 = <&pinctrl_lcdif_dat
  108. + &pinctrl_lcdif_ctrl>;
  109. + display = <&display0>;
  110. + status = "okay";
  111. +
  112. + display0: display {
  113. + mpu-mode;
  114. + lcd_reset_gpio = <&gpio3 14 0>;
  115. + lcd_panel = "ST7789S-QVGA";
  116. + };
  117. +};
  118. +
  119. +&pxp {
  120. + status = "okay";
  121. +};
  122. +
  123. +&tsc {
  124. + pinctrl-names = "default";
  125. + pinctrl-0 = <&pinctrl_tsc>;
  126. + status = "okay";
  127. + xnur-gpio = <&gpio1 3 0>;
  128. + measure_delay_time = <0xffff>;
  129. + pre_charge_time = <0xfff>;
  130. +};
  131. +
  132. +&uart1 {
  133. + pinctrl-names = "default";
  134. + pinctrl-0 = <&pinctrl_uart1>;
  135. + status = "okay";
  136. +};
  137. +
  138. +&usbotg1 {
  139. + dr_mode = "peripheral";
  140. + status = "okay";
  141. +};
  142. +
  143. +&usbotg2 {
  144. + dr_mode = "host";
  145. + disable-over-current;
  146. + status = "okay";
  147. +};
  148. +
  149. +&usdhc1 {
  150. + pinctrl-names = "default", "state_100mhz", "state_200mhz";
  151. + pinctrl-0 = <&pinctrl_usdhc1>;
  152. + pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
  153. + pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
  154. + cd-gpios = <&gpio1 19 0>;
  155. + keep-power-in-suspend;
  156. + enable-sdio-wakeup;
  157. + vmmc-supply = <&reg_sd1_vmmc>;
  158. + status = "okay";
  159. +};
  160. +
  161. +&iomuxc {
  162. + imx6ul-evk {
  163. + pinctrl_lcdif_dat: lcdifdatgrp {
  164. + fsl,pins = <
  165. + MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79
  166. + MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79
  167. + MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79
  168. + MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79
  169. + MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79
  170. + MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79
  171. + MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79
  172. + MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79
  173. + >;
  174. + };
  175. +
  176. + pinctrl_lcdif_ctrl: lcdifctrlgrp {
  177. + fsl,pins = <
  178. + MX6UL_PAD_LCD_CLK__LCDIF_WR_RWN 0x79
  179. + MX6UL_PAD_LCD_ENABLE__LCDIF_RD_E 0x79
  180. + MX6UL_PAD_LCD_HSYNC__LCDIF_RS 0x79
  181. + MX6UL_PAD_LCD_RESET__LCDIF_CS 0x79
  182. + /* used for lcd reset */
  183. + MX6UL_PAD_LCD_DATA09__GPIO3_IO14 0x79
  184. + >;
  185. + };
  186. +
  187. + pinctrl_uart1: uart1grp {
  188. + fsl,pins = <
  189. + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
  190. + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
  191. + >;
  192. + };
  193. +
  194. + pinctrl_usdhc1: usdhc1grp {
  195. + fsl,pins = <
  196. + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
  197. + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071
  198. + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
  199. + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
  200. + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
  201. + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
  202. + >;
  203. + };
  204. +
  205. + pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
  206. + fsl,pins = <
  207. + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9
  208. + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9
  209. + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
  210. + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
  211. + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
  212. + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
  213. + >;
  214. + };
  215. +
  216. + pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
  217. + fsl,pins = <
  218. + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9
  219. + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9
  220. + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
  221. + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
  222. + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
  223. + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
  224. + >;
  225. + };
  226. +
  227. + pinctrl_tsc: tscgrp {
  228. + fsl,pins = <
  229. + MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
  230. + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
  231. + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0
  232. + MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xb0
  233. + >;
  234. + };
  235. + };
  236. +};
  237. diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
  238. index 15b47de9da6c..98b3ba8db058 100644
  239. --- a/arch/arm/configs/imx_v7_defconfig
  240. +++ b/arch/arm/configs/imx_v7_defconfig
  241. @@ -246,6 +246,7 @@ CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E=y
  242. CONFIG_FB_MXC_LDB=y
  243. CONFIG_FB_MXC_HDMI=y
  244. CONFIG_FB_MXS_SII902X=y
  245. +CONFIG_FB_MXS_ST7789S_QVGA=y
  246. CONFIG_FB_MXC_DCIC=m
  247. CONFIG_FB_MXC_ADV7535=y
  248. CONFIG_HANNSTAR_CABC=y
  249. diff --git a/drivers/video/fbdev/mxc/Kconfig b/drivers/video/fbdev/mxc/Kconfig
  250. index 0b79ee371c6d..a34c52393069 100644
  251. --- a/drivers/video/fbdev/mxc/Kconfig
  252. +++ b/drivers/video/fbdev/mxc/Kconfig
  253. @@ -79,6 +79,10 @@ config FB_MXS_SII902X
  254. tristate "Si Image SII9022 DVI/HDMI Interface Chip"
  255. depends on FB_MXS && I2C
  256.  
  257. +config FB_MXS_ST7789S_QVGA
  258. + tristate "ST7789S QVGA MPU Display"
  259. + depends on FB_MXS
  260. +
  261. config FB_MXC_DCIC
  262. tristate "MXC DCIC"
  263. depends on FB_MXC_SYNC_PANEL
  264. diff --git a/drivers/video/fbdev/mxc/Makefile b/drivers/video/fbdev/mxc/Makefile
  265. index a910a3a716ed..81650ec53fcf 100644
  266. --- a/drivers/video/fbdev/mxc/Makefile
  267. +++ b/drivers/video/fbdev/mxc/Makefile
  268. @@ -12,5 +12,6 @@ obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxc_dispdrv.o mxc_lcdif.o mxc_ipuv3_fb.o
  269. obj-$(CONFIG_FB_MXC_EINK_PANEL) += mxc_epdc_fb.o
  270. obj-$(CONFIG_FB_MXC_EINK_V2_PANEL) += mxc_epdc_v2_fb.o
  271. obj-$(CONFIG_FB_MXS_SII902X) += mxsfb_sii902x.o
  272. +obj-$(CONFIG_FB_MXS_ST7789S_QVGA) += mxsfb_st7789s_qvga.o
  273. obj-$(CONFIG_FB_MXC_DCIC) += mxc_dcic.o
  274. obj-$(CONFIG_HANNSTAR_CABC) += hannstar_cabc.o
  275. diff --git a/drivers/video/fbdev/mxc/mxsfb_st7789s_qvga.c b/drivers/video/fbdev/mxc/mxsfb_st7789s_qvga.c
  276. new file mode 100644
  277. index 000000000000..ab8bd84bf546
  278. --- /dev/null
  279. +++ b/drivers/video/fbdev/mxc/mxsfb_st7789s_qvga.c
  280. @@ -0,0 +1,180 @@
  281. +/*
  282. + * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
  283. + *
  284. + * This program is free software; you can redistribute it and/or modify
  285. + * it under the terms of the GNU General Public License as published by
  286. + * the Free Software Foundation; either version 2 of the License, or
  287. + * (at your option) any later version.
  288. +
  289. + * This program is distributed in the hope that it will be useful,
  290. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  291. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  292. + * GNU General Public License for more details.
  293. +
  294. + * You should have received a copy of the GNU General Public License along
  295. + * with this program; if not, write to the Free Software Foundation, Inc.,
  296. + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  297. + */
  298. +
  299. +#include <linux/types.h>
  300. +#include <linux/init.h>
  301. +#include <linux/delay.h>
  302. +#include <linux/err.h>
  303. +#include <linux/io.h>
  304. +
  305. +#include "../mxsfb.h"
  306. +
  307. +static struct fb_videomode st7789s_lcd_modedb[] = {
  308. + {
  309. + "ST7789S-QVGA", 60, 240, 320, 200000,
  310. + 0, 0,
  311. + 0, 0,
  312. + 0, 0,
  313. + 0,
  314. + FB_VMODE_NONINTERLACED,
  315. + 0,
  316. + },
  317. +};
  318. +
  319. +static struct mpu_lcd_config lcd_config = {
  320. + .bus_mode = MPU_BUS_8080,
  321. + .interface_width = 8,
  322. + .panel_bpp = 16,
  323. +};
  324. +void mpu_st7789s_get_lcd_videomode(struct fb_videomode **mode, int *size,
  325. + struct mpu_lcd_config **data)
  326. +{
  327. + *mode = &st7789s_lcd_modedb[0];
  328. + *size = ARRAY_SIZE(st7789s_lcd_modedb);
  329. + *data = &lcd_config;
  330. +}
  331. +
  332. +int mpu_st7789s_lcd_setup(struct mxsfb_info * mxsfb)
  333. +{
  334. + if (mxsfb == NULL)
  335. + return -1;
  336. +
  337. + /* Sleep out */
  338. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x11);
  339. +
  340. + /* Analog setting */
  341. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xB2);
  342. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x0C);
  343. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x0C);
  344. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
  345. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x33);
  346. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x33);
  347. +
  348. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xB7);
  349. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x35);
  350. +
  351. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xBB);
  352. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x35);
  353. +
  354. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xC0);
  355. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x2C);
  356. +
  357. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xC2);
  358. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x01);
  359. +
  360. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xC3);
  361. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x06);
  362. +
  363. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xC4);
  364. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x20);
  365. +
  366. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xC6);
  367. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0xE5);
  368. +
  369. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xD0);
  370. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0xA4);
  371. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0xB1);
  372. +
  373. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x55);
  374. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x90);
  375. +
  376. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xE8);
  377. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x40);
  378. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x10);
  379. +
  380. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xB8);
  381. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x2A);
  382. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x2B);
  383. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x15);
  384. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x75);
  385. +
  386. + /* Gamma setting */
  387. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xE0);
  388. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0xE0);
  389. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
  390. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x02);
  391. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x07);
  392. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x0B);
  393. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x1A);
  394. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x37);
  395. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x54);
  396. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x40);
  397. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x29);
  398. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x12);
  399. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x12);
  400. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x12);
  401. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x17);
  402. +
  403. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0xE1);
  404. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0xE0);
  405. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
  406. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x02);
  407. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x07);
  408. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x05);
  409. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x25);
  410. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x37);
  411. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x44);
  412. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x45);
  413. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x1C);
  414. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x18);
  415. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x16);
  416. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x1C);
  417. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x1D);
  418. +
  419. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x36);
  420. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
  421. +
  422. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x3A);
  423. + if (mxsfb->mpu_lcd_sigs->panel_bpp == 16)
  424. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x55);
  425. + else
  426. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x66); /* 18 bpp */
  427. +
  428. + /* Set row address */
  429. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x2A);
  430. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
  431. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
  432. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, (((st7789s_lcd_modedb[0].xres - 1) >> 8) & 0xFF));
  433. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, ((st7789s_lcd_modedb[0].xres - 1) & 0xFF));
  434. +
  435. + /* Set column address */
  436. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x2B);
  437. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
  438. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, 0x00);
  439. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, (((st7789s_lcd_modedb[0].yres - 1) >> 8) & 0xFF));
  440. + mxsfb_mpu_access(mxsfb, MPU_DATA, MPU_WRITE, ((st7789s_lcd_modedb[0].yres - 1) & 0xFF));
  441. +
  442. + /* Display on */
  443. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x29);
  444. +
  445. + /* Memory write */
  446. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x2C);
  447. +
  448. + return 0;
  449. +}
  450. +
  451. +int mpu_st7789s_lcd_poweroff(struct mxsfb_info * mxsfb)
  452. +{
  453. + /* Display off */
  454. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x28);
  455. +
  456. + /* Sleep in */
  457. + mxsfb_mpu_access(mxsfb, MPU_CMD, MPU_WRITE, 0x10);
  458. +
  459. + return 0;
  460. +}
  461. diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c
  462. index 0d4fe02e3031..17fe13e4b53b 100644
  463. --- a/drivers/video/fbdev/mxsfb.c
  464. +++ b/drivers/video/fbdev/mxsfb.c
  465. @@ -44,6 +44,7 @@
  466. #include <linux/console.h>
  467. #include <linux/module.h>
  468. #include <linux/kernel.h>
  469. +#include <linux/delay.h>
  470. #include <linux/of_device.h>
  471. #include <linux/of_gpio.h>
  472. #include <linux/pm_qos.h>
  473. @@ -64,210 +65,18 @@
  474. #include <linux/uaccess.h>
  475.  
  476. #include "mxc/mxc_dispdrv.h"
  477. +#include "mxsfb.h"
  478.  
  479. -#define REG_SET 4
  480. -#define REG_CLR 8
  481. -
  482. -#define LCDC_CTRL 0x00
  483. -#define LCDC_CTRL1 0x10
  484. -#define LCDC_V4_CTRL2 0x20
  485. -#define LCDC_V3_TRANSFER_COUNT 0x20
  486. -#define LCDC_V4_TRANSFER_COUNT 0x30
  487. -#define LCDC_V4_CUR_BUF 0x40
  488. -#define LCDC_V4_NEXT_BUF 0x50
  489. -#define LCDC_V3_CUR_BUF 0x30
  490. -#define LCDC_V3_NEXT_BUF 0x40
  491. -#define LCDC_TIMING 0x60
  492. -#define LCDC_VDCTRL0 0x70
  493. -#define LCDC_VDCTRL1 0x80
  494. -#define LCDC_VDCTRL2 0x90
  495. -#define LCDC_VDCTRL3 0xa0
  496. -#define LCDC_VDCTRL4 0xb0
  497. -#define LCDC_DVICTRL0 0xc0
  498. -#define LCDC_DVICTRL1 0xd0
  499. -#define LCDC_DVICTRL2 0xe0
  500. -#define LCDC_DVICTRL3 0xf0
  501. -#define LCDC_DVICTRL4 0x100
  502. -#define LCDC_V4_DATA 0x180
  503. -#define LCDC_V3_DATA 0x1b0
  504. -#define LCDC_V4_DEBUG0 0x1d0
  505. -#define LCDC_V3_DEBUG0 0x1f0
  506. -#define LCDC_AS_CTRL 0x210
  507. -#define LCDC_AS_BUF 0x220
  508. -#define LCDC_AS_NEXT_BUF 0x230
  509. -
  510. -#define CTRL_SFTRST (1 << 31)
  511. -#define CTRL_CLKGATE (1 << 30)
  512. -#define CTRL_BYPASS_COUNT (1 << 19)
  513. -#define CTRL_VSYNC_MODE (1 << 18)
  514. -#define CTRL_DOTCLK_MODE (1 << 17)
  515. -#define CTRL_DATA_SELECT (1 << 16)
  516. -#define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10)
  517. -#define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3)
  518. -#define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8)
  519. -#define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3)
  520. -#define CTRL_MASTER (1 << 5)
  521. -#define CTRL_DF16 (1 << 3)
  522. -#define CTRL_DF18 (1 << 2)
  523. -#define CTRL_DF24 (1 << 1)
  524. -#define CTRL_RUN (1 << 0)
  525. -
  526. -#define CTRL1_RECOVERY_ON_UNDERFLOW (1 << 24)
  527. -#define CTRL1_FIFO_CLEAR (1 << 21)
  528. -#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
  529. -#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
  530. -#define CTRL1_OVERFLOW_IRQ_EN (1 << 15)
  531. -#define CTRL1_UNDERFLOW_IRQ_EN (1 << 14)
  532. -#define CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13)
  533. -#define CTRL1_VSYNC_EDGE_IRQ_EN (1 << 12)
  534. -#define CTRL1_OVERFLOW_IRQ (1 << 11)
  535. -#define CTRL1_UNDERFLOW_IRQ (1 << 10)
  536. -#define CTRL1_CUR_FRAME_DONE_IRQ (1 << 9)
  537. -#define CTRL1_VSYNC_EDGE_IRQ (1 << 8)
  538. -#define CTRL1_IRQ_ENABLE_MASK (CTRL1_OVERFLOW_IRQ_EN | \
  539. - CTRL1_UNDERFLOW_IRQ_EN | \
  540. - CTRL1_CUR_FRAME_DONE_IRQ_EN | \
  541. - CTRL1_VSYNC_EDGE_IRQ_EN)
  542. -#define CTRL1_IRQ_ENABLE_SHIFT 12
  543. -#define CTRL1_IRQ_STATUS_MASK (CTRL1_OVERFLOW_IRQ | \
  544. - CTRL1_UNDERFLOW_IRQ | \
  545. - CTRL1_CUR_FRAME_DONE_IRQ | \
  546. - CTRL1_VSYNC_EDGE_IRQ)
  547. -#define CTRL1_IRQ_STATUS_SHIFT 8
  548. -
  549. -#define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21)
  550. -
  551. -#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
  552. -#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
  553. -#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)
  554. -#define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff)
  555. -
  556. -
  557. -#define VDCTRL0_ENABLE_PRESENT (1 << 28)
  558. -#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
  559. -#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
  560. -#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25)
  561. -#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24)
  562. -#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
  563. -#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
  564. -#define VDCTRL0_HALF_LINE (1 << 19)
  565. -#define VDCTRL0_HALF_LINE_MODE (1 << 18)
  566. -#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
  567. -#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
  568. -
  569. -#define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
  570. -#define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
  571. -
  572. -#define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29)
  573. -#define VDCTRL3_VSYNC_ONLY (1 << 28)
  574. -#define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16)
  575. -#define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff)
  576. -#define SET_VERT_WAIT_CNT(x) ((x) & 0xffff)
  577. -#define GET_VERT_WAIT_CNT(x) ((x) & 0xffff)
  578. -
  579. -#define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */
  580. -#define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */
  581. -#define VDCTRL4_SYNC_SIGNALS_ON (1 << 18)
  582. -#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
  583. -
  584. -#define DEBUG0_HSYNC (1 < 26)
  585. -#define DEBUG0_VSYNC (1 < 25)
  586. -
  587. -#define MIN_XRES 120
  588. -#define MIN_YRES 120
  589. -
  590. -#define RED 0
  591. -#define GREEN 1
  592. -#define BLUE 2
  593. -#define TRANSP 3
  594. -
  595. -#define STMLCDIF_8BIT 1 /** pixel data bus to the display is of 8 bit width */
  596. -#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
  597. -#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
  598. -#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
  599. -
  600. -#define FB_SYNC_OE_LOW_ACT 0x80000000
  601. -#define FB_SYNC_CLK_LAT_FALL 0x40000000
  602. -
  603. -enum mxsfb_devtype {
  604. - MXSFB_V3,
  605. - MXSFB_V4,
  606. - MXSFB_V5,
  607. -};
  608. -
  609. -/* CPU dependent register offsets */
  610. -struct mxsfb_devdata {
  611. - unsigned transfer_count;
  612. - unsigned cur_buf;
  613. - unsigned next_buf;
  614. - unsigned debug0;
  615. - unsigned hs_wdth_mask;
  616. - unsigned hs_wdth_shift;
  617. - unsigned ipversion;
  618. - u32 flags;
  619. -};
  620. -
  621. -struct mxsfb_layer;
  622. -
  623. -struct mxsfb_layer_ops {
  624. - void (*enable)(struct mxsfb_layer *ofb);
  625. - void (*disable)(struct mxsfb_layer *ofb);
  626. - void (*setup)(struct mxsfb_layer *ofb);
  627. -};
  628. -
  629. -struct mxsfb_layer {
  630. - struct fb_info *ol_fb;
  631. - int id;
  632. - int registered;
  633. - atomic_t usage;
  634. - int blank_state;
  635. - uint32_t global_alpha;
  636. -
  637. - struct mxsfb_layer_ops *ops;
  638. -
  639. - struct device *dev;
  640. - void __iomem *video_mem;
  641. - unsigned long video_mem_phys;
  642. - size_t video_mem_size;
  643. -
  644. - struct mxsfb_info *fbi;
  645. -};
  646. -
  647. -#define NAME_LEN 32
  648. -
  649. -struct mxsfb_info {
  650. - struct fb_info *fb_info;
  651. - struct platform_device *pdev;
  652. - struct clk *clk_pix;
  653. - struct clk *clk_axi;
  654. - struct clk *clk_disp_axi;
  655. - bool clk_pix_enabled;
  656. - bool clk_axi_enabled;
  657. - bool clk_disp_axi_enabled;
  658. - void __iomem *base; /* registers */
  659. - u32 sync; /* record display timing polarities */
  660. - unsigned allocated_size;
  661. - int enabled;
  662. - unsigned ld_intf_width;
  663. - unsigned dotclk_delay;
  664. - const struct mxsfb_devdata *devdata;
  665. - struct regulator *reg_lcd;
  666. - bool wait4vsync;
  667. - struct completion vsync_complete;
  668. - struct completion flip_complete;
  669. - int cur_blank;
  670. - int restore_blank;
  671. - char disp_dev[NAME_LEN];
  672. - struct mxc_dispdrv_handle *dispdrv;
  673. - int id;
  674. - struct fb_var_screeninfo var;
  675. - struct pm_qos_request pm_qos_req;
  676. -
  677. - char disp_videomode[NAME_LEN];
  678. -
  679. -#ifdef CONFIG_FB_MXC_OVERLAY
  680. - struct mxsfb_layer overlay;
  681. +static struct mpu_match_lcd mpu_lcd_db[] = {
  682. +#ifdef CONFIG_FB_MXS_ST7789S_QVGA
  683. + {
  684. + "ST7789S-QVGA",
  685. + {mpu_st7789s_get_lcd_videomode, mpu_st7789s_lcd_setup, mpu_st7789s_lcd_poweroff}
  686. + },
  687. #endif
  688. + {
  689. + "", {NULL, NULL}
  690. + }
  691. };
  692.  
  693. #define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
  694. @@ -281,6 +90,7 @@ struct mxsfb_info {
  695. static const struct mxsfb_devdata mxsfb_devdata[] = {
  696. [MXSFB_V3] = {
  697. .transfer_count = LCDC_V3_TRANSFER_COUNT,
  698. + .data = LCDC_V3_DATA,
  699. .cur_buf = LCDC_V3_CUR_BUF,
  700. .next_buf = LCDC_V3_NEXT_BUF,
  701. .debug0 = LCDC_V3_DEBUG0,
  702. @@ -291,6 +101,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
  703. },
  704. [MXSFB_V4] = {
  705. .transfer_count = LCDC_V4_TRANSFER_COUNT,
  706. + .data = LCDC_V4_DATA,
  707. .cur_buf = LCDC_V4_CUR_BUF,
  708. .next_buf = LCDC_V4_NEXT_BUF,
  709. .debug0 = LCDC_V4_DEBUG0,
  710. @@ -559,6 +370,322 @@ static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf)
  711. return chan << bf->offset;
  712. }
  713.  
  714. +static int mxsfb_mpu_wait_for_ready(struct mxsfb_info *host)
  715. +{
  716. + unsigned int val;
  717. + int timeout = 0;
  718. +
  719. + // Check for running
  720. + val = readl(host->base + LCDC_CTRL);
  721. + while(val & CTRL_RUN) {
  722. + mdelay(1);
  723. + timeout ++;
  724. + if (timeout >= 1000) {
  725. + dev_err(&host->pdev->dev, "mxsfb_mpu_wait_for_ready timeout!\n");
  726. + return -ETIME;
  727. + }
  728. + val = readl(host->base + LCDC_CTRL);
  729. + }
  730. +
  731. + return 0;
  732. +}
  733. +unsigned int mxsfb_mpu_access(struct mxsfb_info *host, int mode, int rw, int data)
  734. +{
  735. + unsigned int val, wordlen, ret = 0;
  736. +
  737. + if (mxsfb_mpu_wait_for_ready(host) != 0)
  738. + return 0;
  739. +
  740. + writel(CTRL_MASTER,
  741. + host->base + LCDC_CTRL + REG_CLR);
  742. +
  743. + writel(CTRL1_BYTE_PACKING_FORMAT_MASK,
  744. + host->base + LCDC_CTRL1 + REG_CLR);
  745. + val = readl(host->base + LCDC_CTRL);
  746. + wordlen = CTRL_GET_WORD_LENGTH(val);
  747. + writel(CTRL_WORD_LENGTH_MASK,
  748. + host->base + LCDC_CTRL + REG_CLR);
  749. +
  750. + writel(CTRL_YCBCR422_INPUT |
  751. + CTRL_INPUT_DATA_SWIZZLE_MASK,
  752. + host->base + LCDC_CTRL + REG_CLR);
  753. +
  754. + switch (host->mpu_lcd_sigs->interface_width)
  755. + {
  756. + case 8:
  757. + writel((0x1 << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
  758. + host->base + LCDC_CTRL1 + REG_SET);
  759. + writel(CTRL_WORD_LENGTH_8BIT,
  760. + host->base + LCDC_CTRL + REG_SET);
  761. + break;
  762. + case 16:
  763. + writel((0x3 << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
  764. + host->base + LCDC_CTRL1 + REG_SET);
  765. + writel(CTRL_WORD_LENGTH_16BIT,
  766. + host->base + LCDC_CTRL + REG_SET);
  767. + break;
  768. + }
  769. +
  770. + val = readl(host->base + host->devdata->transfer_count);
  771. + val &= ~(TRANSFER_COUNT_H_COUNT_MASK |
  772. + TRANSFER_COUNT_V_COUNT_MASK);
  773. + val |= (1 << TRANSFER_COUNT_V_COUNT_OFFSET) |
  774. + (1 << TRANSFER_COUNT_H_COUNT_OFFSET);
  775. + writel(val, host->base + host->devdata->transfer_count);
  776. +
  777. + if(mode == MPU_CMD)
  778. + {
  779. + if (host->mpu_lcd_sigs->lcd_rs_is_gpio)
  780. + gpio_set_value(host->mpu_lcd_sigs->lcd_rs_gpio, 0);
  781. + writel(CTRL_DATA_SELECT,
  782. + host->base + LCDC_CTRL + REG_CLR);
  783. + }
  784. + else
  785. + {
  786. + if (host->mpu_lcd_sigs->lcd_rs_is_gpio)
  787. + gpio_set_value(host->mpu_lcd_sigs->lcd_rs_gpio, 1);
  788. + writel(CTRL_DATA_SELECT,
  789. + host->base + LCDC_CTRL + REG_SET);
  790. + }
  791. +
  792. + if(rw == MPU_READ)
  793. + {
  794. + writel(CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_MASK,
  795. + host->base + LCDC_V4_CTRL2 + REG_CLR);
  796. + writel((0x1 << CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_OFFSET),
  797. + host->base + LCDC_V4_CTRL2 + REG_SET);
  798. +
  799. + writel(CTRL_READ_WRITEB,
  800. + host->base + LCDC_CTRL + REG_SET);
  801. + writel(CTRL_RUN,
  802. + host->base + LCDC_CTRL + REG_SET);
  803. + }
  804. + else
  805. + {
  806. + writel(CTRL_READ_WRITEB,
  807. + host->base + LCDC_CTRL + REG_CLR);
  808. + writel(CTRL_RUN,
  809. + host->base + LCDC_CTRL + REG_SET);
  810. +
  811. + writel(data,
  812. + host->base + host->devdata->data);
  813. + }
  814. +
  815. + val = readl(host->base + LCDC_CTRL);
  816. + while(val & CTRL_RUN)
  817. + {
  818. + if(rw == MPU_READ)
  819. + ret = readl(host->base + host->devdata->data);
  820. +
  821. + val = readl(host->base + LCDC_CTRL);
  822. + }
  823. +
  824. + writel(CTRL_MASTER,
  825. + host->base + LCDC_CTRL + REG_SET);
  826. +
  827. + writel(CTRL_WORD_LENGTH_MASK,
  828. + host->base + LCDC_CTRL + REG_CLR);
  829. + writel((wordlen << CTRL_WORD_LENGTH_OFFSET),
  830. + host->base + LCDC_CTRL + REG_SET); // 32 bits valid data
  831. + writel(CTRL1_BYTE_PACKING_FORMAT_MASK,
  832. + host->base + LCDC_CTRL1 + REG_CLR);
  833. + writel((0xF << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
  834. + host->base + LCDC_CTRL1 + REG_SET); // 32 bits valid data
  835. +
  836. + writel(CTRL_MASTER,
  837. + host->base + LCDC_CTRL + REG_SET);
  838. +
  839. + // For idle, set LCD_RS to high
  840. + if (host->mpu_lcd_sigs->lcd_rs_is_gpio)
  841. + gpio_set_value(host->mpu_lcd_sigs->lcd_rs_gpio, 1);
  842. +
  843. + return ret;
  844. +}
  845. +
  846. +int mxsfb_mpu_refresh_panel(struct mxsfb_info *host)
  847. +{
  848. + if (mxsfb_mpu_wait_for_ready(host) != 0)
  849. + return -ETIME;
  850. +
  851. + writel(CTRL_MASTER,
  852. + host->base + LCDC_CTRL + REG_SET);
  853. + writel(CTRL_RUN,
  854. + host->base + LCDC_CTRL + REG_SET);
  855. + return 0;
  856. +}
  857. +
  858. +void mxsfb_mpu_setup_refresh_data(struct mxsfb_info *host)
  859. +{
  860. + unsigned int val;
  861. +
  862. + if (mxsfb_mpu_wait_for_ready(host) != 0)
  863. + return;
  864. +
  865. + val = readl(host->base + host->devdata->transfer_count);
  866. + val &= ~(TRANSFER_COUNT_H_COUNT_MASK |
  867. + TRANSFER_COUNT_V_COUNT_MASK);
  868. + val |= (host->var.xres << TRANSFER_COUNT_H_COUNT_OFFSET) |
  869. + (host->var.yres << TRANSFER_COUNT_V_COUNT_OFFSET);
  870. + writel(val, host->base + host->devdata->transfer_count);
  871. +
  872. + writel(CTRL_READ_WRITEB,
  873. + host->base + LCDC_CTRL + REG_CLR);
  874. + writel(CTRL_BYPASS_COUNT,
  875. + host->base + LCDC_CTRL + REG_CLR);
  876. + writel(CTRL_DATA_SELECT,
  877. + host->base + LCDC_CTRL + REG_SET);
  878. + if (host->mpu_lcd_sigs->lcd_rs_is_gpio)
  879. + gpio_set_value(host->mpu_lcd_sigs->lcd_rs_gpio, 1);
  880. +
  881. + if (host->mpu_lcd_sigs->panel_bpp == 16) {
  882. + writel(CTRL_YCBCR422_INPUT |
  883. + (1 << CTRL_INPUT_DATA_SWIZZLE_OFFSET),
  884. + host->base + LCDC_CTRL + REG_SET);
  885. + }
  886. +}
  887. +
  888. +static void mxsfb_mpu_setup_interface(struct mxsfb_info *host)
  889. +{
  890. + writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
  891. + writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_CLR);
  892. +
  893. + /* Setup the bus protocol */
  894. + if (host->mpu_lcd_sigs->bus_mode == MPU_BUS_8080)
  895. + writel(CTRL1_MODE86,
  896. + host->base + LCDC_CTRL1 + REG_CLR);
  897. + else
  898. + writel(CTRL1_MODE86,
  899. + host->base + LCDC_CTRL1 + REG_SET);
  900. +
  901. + writel(CTRL1_BUSY_ENABLE,
  902. + host->base + LCDC_CTRL1 + REG_CLR);
  903. +
  904. + /* Take display out of reset */
  905. + writel(CTRL1_RESET,
  906. + host->base + LCDC_CTRL1 + REG_SET);
  907. + if (host->mpu_lcd_sigs->lcd_reset_is_gpio)
  908. + gpio_set_value(host->mpu_lcd_sigs->lcd_reset_gpio, 1);
  909. +
  910. + /* VSYNC is an input by default */
  911. + writel(VDCTRL0_VSYNC_OEB,
  912. + host->base + LCDC_VDCTRL0 + REG_SET);
  913. +
  914. + /*
  915. + * Make sure we do a high-to-low transition to reset the panel.
  916. + * First make it low for 100 msec, hi for 10 msec, low for 10 msec,
  917. + * then hi.
  918. + */
  919. + writel(CTRL1_RESET,
  920. + host->base + LCDC_CTRL1 + REG_CLR); /* low */
  921. + if (host->mpu_lcd_sigs->lcd_reset_is_gpio)
  922. + gpio_set_value(host->mpu_lcd_sigs->lcd_reset_gpio, 0);
  923. +
  924. + msleep(100);
  925. +
  926. + writel(CTRL1_RESET,
  927. + host->base + LCDC_CTRL1 + REG_SET); /* high */
  928. + if (host->mpu_lcd_sigs->lcd_reset_is_gpio)
  929. + gpio_set_value(host->mpu_lcd_sigs->lcd_reset_gpio, 1);
  930. +
  931. + msleep(10);
  932. +
  933. + writel(CTRL1_RESET,
  934. + host->base + LCDC_CTRL1 + REG_CLR); /* low */
  935. + if (host->mpu_lcd_sigs->lcd_reset_is_gpio)
  936. + gpio_set_value(host->mpu_lcd_sigs->lcd_reset_gpio, 0);
  937. +
  938. + /* For some panel, Reset must be held low at least 30 uSec
  939. + * Therefore, we'll hold it low for about 10 mSec just to be sure.
  940. + * Then we'll wait 1 mSec afterwards.
  941. + */
  942. + msleep(10);
  943. + writel(CTRL1_RESET,
  944. + host->base + LCDC_CTRL1 + REG_SET); /* high */
  945. + if (host->mpu_lcd_sigs->lcd_reset_is_gpio)
  946. + gpio_set_value(host->mpu_lcd_sigs->lcd_reset_gpio, 1);
  947. + msleep(1);
  948. +
  949. + writel(CTRL_DATA_SHIFT_DIR,
  950. + host->base + LCDC_CTRL + REG_CLR);
  951. +
  952. + writel(CTRL_SHIFT_NUM_BITS_MASK,
  953. + host->base + LCDC_CTRL + REG_CLR);
  954. +
  955. + writel(CTRL2_OUTSTANDING_REQS_MASK,
  956. + host->base + LCDC_V4_CTRL2 + REG_CLR);
  957. + writel(CTRL2_OUTSTANDING_REQS_REQ_8,
  958. + host->base + LCDC_V4_CTRL2 + REG_SET);
  959. +
  960. + /* Recover on underflow */
  961. + writel(CTRL1_RECOVERY_ON_UNDERFLOW,
  962. + host->base + LCDC_CTRL1 + REG_SET);
  963. +
  964. + /* Configure the input pixel format */
  965. + writel(CTRL_YCBCR422_INPUT |
  966. + CTRL_WORD_LENGTH_MASK |
  967. + CTRL_INPUT_DATA_SWIZZLE_MASK |
  968. + CTRL_DATA_FORMAT_16_BIT |
  969. + CTRL_DATA_FORMAT_18_BIT |
  970. + CTRL_DATA_FORMAT_24_BIT,
  971. + host->base + LCDC_CTRL + REG_CLR);
  972. + writel(CTRL1_BYTE_PACKING_FORMAT_MASK,
  973. + host->base + LCDC_CTRL1 + REG_CLR);
  974. + switch (host->mpu_lcd_sigs->panel_bpp) {
  975. + case 16:
  976. + writel((0xF << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
  977. + host->base + LCDC_CTRL1 + REG_SET);
  978. + writel(CTRL_WORD_LENGTH_16BIT |
  979. + (0 << CTRL_INPUT_DATA_SWIZZLE_OFFSET),
  980. + host->base + LCDC_CTRL + REG_SET);
  981. + break;
  982. + case 18:
  983. + writel((0xF << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
  984. + host->base + LCDC_CTRL1 + REG_SET);
  985. + writel(CTRL_WORD_LENGTH_18BIT |
  986. + (0 << CTRL_INPUT_DATA_SWIZZLE_OFFSET),
  987. + host->base + LCDC_CTRL + REG_SET);
  988. + break;
  989. + case 24:
  990. + default:
  991. + writel((0xF << CTRL1_BYTE_PACKING_FORMAT_OFFSET),
  992. + host->base + LCDC_CTRL1 + REG_SET);
  993. + writel(CTRL_WORD_LENGTH_24BIT|
  994. + (0 << CTRL_INPUT_DATA_SWIZZLE_OFFSET),
  995. + host->base + LCDC_CTRL + REG_SET);
  996. + break;
  997. + }
  998. +
  999. + /* Configure the output bus width */
  1000. + writel(CTRL_LCD_DATABUS_WIDTH_MASK,
  1001. + host->base + LCDC_CTRL + REG_CLR);
  1002. + switch (host->mpu_lcd_sigs->interface_width) {
  1003. + case 8:
  1004. + writel(CTRL_LCD_DATABUS_WIDTH_8BIT,
  1005. + host->base + LCDC_CTRL + REG_SET);
  1006. + break;
  1007. + case 16:
  1008. + writel(CTRL_LCD_DATABUS_WIDTH_16BIT,
  1009. + host->base + LCDC_CTRL + REG_SET);
  1010. + break;
  1011. + case 18:
  1012. + writel(CTRL_LCD_DATABUS_WIDTH_18BIT,
  1013. + host->base + LCDC_CTRL + REG_SET);
  1014. + break;
  1015. + case 24:
  1016. + default:
  1017. + writel(CTRL_LCD_DATABUS_WIDTH_24BIT,
  1018. + host->base + LCDC_CTRL + REG_SET);
  1019. + break;
  1020. + }
  1021. +
  1022. + /* Configure the MPU timing */
  1023. + writel((1 << TIMING_CMD_HOLD_OFFSET) | (1 << TIMING_CMD_SETUP_OFFSET) |
  1024. + (1 << TIMING_DATA_HOLD_OFFSET) | (1 << TIMING_DATA_SETUP_OFFSET),
  1025. + host->base + LCDC_TIMING);
  1026. +
  1027. + msleep(10);
  1028. +}
  1029. +
  1030. static irqreturn_t mxsfb_irq_handler(int irq, void *dev_id)
  1031. {
  1032. struct mxsfb_info *host = dev_id;
  1033. @@ -625,6 +752,11 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
  1034. rgb = def_rgb565;
  1035. break;
  1036. case 32:
  1037. + if (host->is_mpu_lcd) {
  1038. + rgb = def_rgb888;
  1039. + break;
  1040. + }
  1041. +
  1042. switch (host->ld_intf_width) {
  1043. case STMLCDIF_8BIT:
  1044. pr_debug("Unsupported LCD bus width mapping\n");
  1045. @@ -727,22 +859,24 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
  1046. }
  1047. clk_enable_pix(host);
  1048.  
  1049. - writel(CTRL2_OUTSTANDING_REQS__REQ_16,
  1050. - host->base + LCDC_V4_CTRL2 + REG_SET);
  1051. + if (!host->is_mpu_lcd) {
  1052. + writel(CTRL2_OUTSTANDING_REQS_REQ_16,
  1053. + host->base + LCDC_V4_CTRL2 + REG_SET);
  1054.  
  1055. - /* if it was disabled, re-enable the mode again */
  1056. - writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
  1057. + /* if it was disabled, re-enable the mode again */
  1058. + writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
  1059.  
  1060. - /* enable the SYNC signals first, then the DMA engine */
  1061. - reg = readl(host->base + LCDC_VDCTRL4);
  1062. - reg |= VDCTRL4_SYNC_SIGNALS_ON;
  1063. - writel(reg, host->base + LCDC_VDCTRL4);
  1064. + /* enable the SYNC signals first, then the DMA engine */
  1065. + reg = readl(host->base + LCDC_VDCTRL4);
  1066. + reg |= VDCTRL4_SYNC_SIGNALS_ON;
  1067. + writel(reg, host->base + LCDC_VDCTRL4);
  1068.  
  1069. - writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_SET);
  1070. - writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
  1071. + writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_SET);
  1072. + writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
  1073.  
  1074. - /* Recovery on underflow */
  1075. - writel(CTRL1_RECOVERY_ON_UNDERFLOW, host->base + LCDC_CTRL1 + REG_SET);
  1076. + /* Recovery on underflow */
  1077. + writel(CTRL1_RECOVERY_ON_UNDERFLOW, host->base + LCDC_CTRL1 + REG_SET);
  1078. + }
  1079.  
  1080. host->enabled = 1;
  1081.  
  1082. @@ -851,107 +985,122 @@ static int mxsfb_set_par(struct fb_info *fb_info)
  1083. * This may lead into shifted pictures (FIFO issue?).
  1084. * So, first stop the controller and drain its FIFOs
  1085. */
  1086. - if (host->enabled) {
  1087. + if (host->enabled && (!host->is_mpu_lcd)) {
  1088. reenable = 1;
  1089. mxsfb_disable_controller(fb_info);
  1090. }
  1091.  
  1092. - /* clear the FIFOs */
  1093. - writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
  1094. -
  1095. - ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
  1096. - CTRL_SET_BUS_WIDTH(host->ld_intf_width);
  1097. -
  1098. - switch (fb_info->var.bits_per_pixel) {
  1099. - case 16:
  1100. - dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n");
  1101. - ctrl |= CTRL_SET_WORD_LENGTH(0);
  1102. - writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1);
  1103. - break;
  1104. - case 32:
  1105. - dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
  1106. - ctrl |= CTRL_SET_WORD_LENGTH(3);
  1107. - switch (host->ld_intf_width) {
  1108. - case STMLCDIF_8BIT:
  1109. - dev_dbg(&host->pdev->dev,
  1110. - "Unsupported LCD bus width mapping\n");
  1111. - return -EINVAL;
  1112. - case STMLCDIF_16BIT:
  1113. - /* 24 bit to 18 bit mapping */
  1114. - ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
  1115. - * each colour component
  1116. - */
  1117. + if (host->is_mpu_lcd) {
  1118. + if (host->enabled) {
  1119. + mxsfb_mpu_setup_interface(host);
  1120. + writel(fb_info->fix.smem_start +
  1121. + fb_info->fix.line_length * fb_info->var.yoffset,
  1122. + host->base + host->devdata->cur_buf);
  1123. + writel(fb_info->fix.smem_start +
  1124. + fb_info->fix.line_length * fb_info->var.yoffset,
  1125. + host->base + host->devdata->next_buf);
  1126. + host->mpu_lcd_functions->mpu_lcd_setup(host);
  1127. + mxsfb_mpu_setup_refresh_data(host);
  1128. + mxsfb_mpu_refresh_panel(host);
  1129. + }
  1130. + } else {
  1131. + /* clear the FIFOs */
  1132. + writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
  1133. +
  1134. + ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
  1135. + CTRL_SET_BUS_WIDTH(host->ld_intf_width);
  1136. +
  1137. + switch (fb_info->var.bits_per_pixel) {
  1138. + case 16:
  1139. + dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n");
  1140. + ctrl |= CTRL_SET_WORD_LENGTH(0);
  1141. + writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1);
  1142. break;
  1143. - case STMLCDIF_18BIT:
  1144. - if (pixfmt_is_equal(&fb_info->var, def_rgb666))
  1145. + case 32:
  1146. + dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
  1147. + ctrl |= CTRL_SET_WORD_LENGTH(3);
  1148. + switch (host->ld_intf_width) {
  1149. + case STMLCDIF_8BIT:
  1150. + dev_dbg(&host->pdev->dev,
  1151. + "Unsupported LCD bus width mapping\n");
  1152. + return -EINVAL;
  1153. + case STMLCDIF_16BIT:
  1154. /* 24 bit to 18 bit mapping */
  1155. - ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
  1156. - * each colour component
  1157. - */
  1158. - break;
  1159. - case STMLCDIF_24BIT:
  1160. - /* real 24 bit */
  1161. + ctrl |= CTRL_DATA_FORMAT_24_BIT; /* ignore the upper 2 bits in
  1162. + * each colour component
  1163. + */
  1164. + break;
  1165. + case STMLCDIF_18BIT:
  1166. + if (pixfmt_is_equal(&fb_info->var, def_rgb666))
  1167. + /* 24 bit to 18 bit mapping */
  1168. + ctrl |= CTRL_DATA_FORMAT_24_BIT; /* ignore the upper 2 bits in
  1169. + * each colour component
  1170. + */
  1171. + break;
  1172. + case STMLCDIF_24BIT:
  1173. + /* real 24 bit */
  1174. + break;
  1175. + }
  1176. + /* do not use packed pixels = one pixel per word instead */
  1177. + writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
  1178. break;
  1179. + default:
  1180. + dev_dbg(&host->pdev->dev, "Unhandled color depth of %u\n",
  1181. + fb_info->var.bits_per_pixel);
  1182. + return -EINVAL;
  1183. }
  1184. - /* do not use packed pixels = one pixel per word instead */
  1185. - writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
  1186. - break;
  1187. - default:
  1188. - dev_dbg(&host->pdev->dev, "Unhandled color depth of %u\n",
  1189. - fb_info->var.bits_per_pixel);
  1190. - return -EINVAL;
  1191. - }
  1192.  
  1193. - writel(ctrl, host->base + LCDC_CTRL);
  1194. -
  1195. - writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
  1196. - TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
  1197. - host->base + host->devdata->transfer_count);
  1198. -
  1199. - vdctrl0 = VDCTRL0_ENABLE_PRESENT | /* always in DOTCLOCK mode */
  1200. - VDCTRL0_VSYNC_PERIOD_UNIT |
  1201. - VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
  1202. - VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
  1203. - /* use the saved sync to avoid wrong sync information */
  1204. - if (host->sync & FB_SYNC_HOR_HIGH_ACT)
  1205. - vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
  1206. - if (host->sync & FB_SYNC_VERT_HIGH_ACT)
  1207. - vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
  1208. - if (!(host->sync & FB_SYNC_OE_LOW_ACT))
  1209. - vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
  1210. - if (host->sync & FB_SYNC_CLK_LAT_FALL)
  1211. - vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
  1212. -
  1213. - writel(vdctrl0, host->base + LCDC_VDCTRL0);
  1214. -
  1215. - /* frame length in lines */
  1216. - writel(fb_info->var.upper_margin + fb_info->var.vsync_len +
  1217. - fb_info->var.lower_margin + fb_info->var.yres,
  1218. - host->base + LCDC_VDCTRL1);
  1219. -
  1220. - /* line length in units of clocks or pixels */
  1221. - writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) |
  1222. - VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin +
  1223. - fb_info->var.hsync_len + fb_info->var.right_margin +
  1224. - fb_info->var.xres),
  1225. - host->base + LCDC_VDCTRL2);
  1226. -
  1227. - writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin +
  1228. - fb_info->var.hsync_len) |
  1229. - SET_VERT_WAIT_CNT(fb_info->var.upper_margin +
  1230. - fb_info->var.vsync_len),
  1231. - host->base + LCDC_VDCTRL3);
  1232. -
  1233. - vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres);
  1234. - if (mxsfb_is_v4(host))
  1235. - vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay);
  1236. - writel(vdctrl4, host->base + LCDC_VDCTRL4);
  1237. -
  1238. - writel(fb_info->fix.smem_start +
  1239. - fb_info->fix.line_length * fb_info->var.yoffset,
  1240. - host->base + host->devdata->next_buf);
  1241. -
  1242. - if (reenable)
  1243. + writel(ctrl, host->base + LCDC_CTRL);
  1244. +
  1245. + writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
  1246. + TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
  1247. + host->base + host->devdata->transfer_count);
  1248. +
  1249. + vdctrl0 = VDCTRL0_ENABLE_PRESENT | /* always in DOTCLOCK mode */
  1250. + VDCTRL0_VSYNC_PERIOD_UNIT |
  1251. + VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
  1252. + VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
  1253. + /* use the saved sync to avoid wrong sync information */
  1254. + if (host->sync & FB_SYNC_HOR_HIGH_ACT)
  1255. + vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
  1256. + if (host->sync & FB_SYNC_VERT_HIGH_ACT)
  1257. + vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
  1258. + if (!(host->sync & FB_SYNC_OE_LOW_ACT))
  1259. + vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
  1260. + if (host->sync & FB_SYNC_CLK_LAT_FALL)
  1261. + vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
  1262. +
  1263. + writel(vdctrl0, host->base + LCDC_VDCTRL0);
  1264. +
  1265. + /* frame length in lines */
  1266. + writel(fb_info->var.upper_margin + fb_info->var.vsync_len +
  1267. + fb_info->var.lower_margin + fb_info->var.yres,
  1268. + host->base + LCDC_VDCTRL1);
  1269. +
  1270. + /* line length in units of clocks or pixels */
  1271. + writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) |
  1272. + VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin +
  1273. + fb_info->var.hsync_len + fb_info->var.right_margin +
  1274. + fb_info->var.xres),
  1275. + host->base + LCDC_VDCTRL2);
  1276. +
  1277. + writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin +
  1278. + fb_info->var.hsync_len) |
  1279. + SET_VERT_WAIT_CNT(fb_info->var.upper_margin +
  1280. + fb_info->var.vsync_len),
  1281. + host->base + LCDC_VDCTRL3);
  1282. +
  1283. + vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres);
  1284. + if (mxsfb_is_v4(host))
  1285. + vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay);
  1286. + writel(vdctrl4, host->base + LCDC_VDCTRL4);
  1287. +
  1288. + writel(fb_info->fix.smem_start +
  1289. + fb_info->fix.line_length * fb_info->var.yoffset,
  1290. + host->base + host->devdata->next_buf);
  1291. + }
  1292. +
  1293. + if (reenable && (!host->is_mpu_lcd))
  1294. mxsfb_enable_controller(fb_info);
  1295.  
  1296. /* Clear activate as not Reconfiguring framebuffer again */
  1297. @@ -1014,20 +1163,25 @@ static int mxsfb_wait_for_vsync(struct fb_info *fb_info)
  1298. return -EINVAL;
  1299. }
  1300.  
  1301. - init_completion(&host->vsync_complete);
  1302. + if (host->is_mpu_lcd) {
  1303. + if (mxsfb_mpu_wait_for_ready(host) != 0)
  1304. + return -ETIME;
  1305. + } else {
  1306. + init_completion(&host->vsync_complete);
  1307.  
  1308. - host->wait4vsync = 1;
  1309. - writel(CTRL1_VSYNC_EDGE_IRQ_EN,
  1310. - host->base + LCDC_CTRL1 + REG_SET);
  1311. - ret = wait_for_completion_interruptible_timeout(
  1312. - &host->vsync_complete, 1 * HZ);
  1313. - if (ret == 0) {
  1314. - dev_err(fb_info->device,
  1315. - "mxs wait for vsync timeout\n");
  1316. - host->wait4vsync = 0;
  1317. - ret = -ETIME;
  1318. - } else if (ret > 0) {
  1319. - ret = 0;
  1320. + host->wait4vsync = 1;
  1321. + writel(CTRL1_VSYNC_EDGE_IRQ_EN,
  1322. + host->base + LCDC_CTRL1 + REG_SET);
  1323. + ret = wait_for_completion_interruptible_timeout(
  1324. + &host->vsync_complete, 1 * HZ);
  1325. + if (ret == 0) {
  1326. + dev_err(fb_info->device,
  1327. + "mxs wait for vsync timeout\n");
  1328. + host->wait4vsync = 0;
  1329. + ret = -ETIME;
  1330. + } else if (ret > 0) {
  1331. + ret = 0;
  1332. + }
  1333. }
  1334. return ret;
  1335. }
  1336. @@ -1035,12 +1189,16 @@ static int mxsfb_wait_for_vsync(struct fb_info *fb_info)
  1337. static int mxsfb_ioctl(struct fb_info *fb_info, unsigned int cmd,
  1338. unsigned long arg)
  1339. {
  1340. + struct mxsfb_info *host = fb_info->par;
  1341. int ret = -EINVAL;
  1342.  
  1343. switch (cmd) {
  1344. case MXCFB_WAIT_FOR_VSYNC:
  1345. ret = mxsfb_wait_for_vsync(fb_info);
  1346. break;
  1347. + case MXCFB_MPU_REFRESH_PANEL:
  1348. + ret = mxsfb_mpu_refresh_panel(host);
  1349. + break;
  1350. default:
  1351. break;
  1352. }
  1353. @@ -1059,6 +1217,8 @@ static int mxsfb_blank(int blank, struct fb_info *fb_info)
  1354. case FB_BLANK_HSYNC_SUSPEND:
  1355. case FB_BLANK_NORMAL:
  1356. if (host->enabled) {
  1357. + if (host->is_mpu_lcd)
  1358. + host->mpu_lcd_functions->mpu_lcd_poweroff(host);
  1359. mxsfb_disable_controller(fb_info);
  1360. pm_runtime_put_sync_suspend(&host->pdev->dev);
  1361. }
  1362. @@ -1080,8 +1240,13 @@ static int mxsfb_blank(int blank, struct fb_info *fb_info)
  1363. pm_runtime_get_sync(&host->pdev->dev);
  1364.  
  1365. writel(0, host->base + LCDC_CTRL);
  1366. - mxsfb_set_par(host->fb_info);
  1367. - mxsfb_enable_controller(fb_info);
  1368. + if (host->is_mpu_lcd) {
  1369. + mxsfb_enable_controller(fb_info);
  1370. + mxsfb_set_par(host->fb_info);
  1371. + } else {
  1372. + mxsfb_set_par(host->fb_info);
  1373. + mxsfb_enable_controller(fb_info);
  1374. + }
  1375. }
  1376. break;
  1377. }
  1378. @@ -1111,24 +1276,37 @@ static int mxsfb_pan_display(struct fb_var_screeninfo *var,
  1379. return -EINVAL;
  1380. }
  1381.  
  1382. - init_completion(&host->flip_complete);
  1383. + if (host->is_mpu_lcd) {
  1384. + if (mxsfb_mpu_wait_for_ready(host) != 0)
  1385. + return -ETIMEDOUT;
  1386.  
  1387. - offset = fb_info->fix.line_length * var->yoffset;
  1388. + offset = fb_info->fix.line_length * var->yoffset;
  1389.  
  1390. - /* update on next VSYNC */
  1391. - writel(fb_info->fix.smem_start + offset,
  1392. - host->base + host->devdata->next_buf);
  1393. + writel(fb_info->fix.smem_start + offset,
  1394. + host->base + host->devdata->next_buf);
  1395. + writel(fb_info->fix.smem_start + offset,
  1396. + host->base + host->devdata->cur_buf);
  1397.  
  1398. - writel(CTRL1_CUR_FRAME_DONE_IRQ_EN,
  1399. - host->base + LCDC_CTRL1 + REG_SET);
  1400. + mxsfb_mpu_refresh_panel(host);
  1401. + } else {
  1402. + init_completion(&host->flip_complete);
  1403.  
  1404. - ret = wait_for_completion_timeout(&host->flip_complete, HZ / 2);
  1405. - if (!ret) {
  1406. - dev_err(fb_info->device,
  1407. - "mxs wait for pan flip timeout\n");
  1408. - return -ETIMEDOUT;
  1409. - }
  1410. + offset = fb_info->fix.line_length * var->yoffset;
  1411. +
  1412. + /* update on next VSYNC */
  1413. + writel(fb_info->fix.smem_start + offset,
  1414. + host->base + host->devdata->next_buf);
  1415. +
  1416. + writel(CTRL1_CUR_FRAME_DONE_IRQ_EN,
  1417. + host->base + LCDC_CTRL1 + REG_SET);
  1418.  
  1419. + ret = wait_for_completion_timeout(&host->flip_complete, HZ / 2);
  1420. + if (!ret) {
  1421. + dev_err(fb_info->device,
  1422. + "mxs wait for pan flip timeout\n");
  1423. + return -ETIMEDOUT;
  1424. + }
  1425. + }
  1426. return 0;
  1427. }
  1428.  
  1429. @@ -1194,86 +1372,88 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
  1430. */
  1431. clk_enable_pix(host);
  1432.  
  1433. - /* Only restore the mode when the controller is running */
  1434. - ctrl = readl(host->base + LCDC_CTRL);
  1435. - if (!(ctrl & CTRL_RUN))
  1436. - return -EINVAL;
  1437. + if (! host->is_mpu_lcd) {
  1438. + /* Only restore the mode when the controller is running */
  1439. + ctrl = readl(host->base + LCDC_CTRL);
  1440. + if (!(ctrl & CTRL_RUN))
  1441. + return -EINVAL;
  1442.  
  1443. - memset(&vmode, 0, sizeof(vmode));
  1444. + memset(&vmode, 0, sizeof(vmode));
  1445.  
  1446. - vdctrl0 = readl(host->base + LCDC_VDCTRL0);
  1447. - vdctrl2 = readl(host->base + LCDC_VDCTRL2);
  1448. - vdctrl3 = readl(host->base + LCDC_VDCTRL3);
  1449. - vdctrl4 = readl(host->base + LCDC_VDCTRL4);
  1450. + vdctrl0 = readl(host->base + LCDC_VDCTRL0);
  1451. + vdctrl2 = readl(host->base + LCDC_VDCTRL2);
  1452. + vdctrl3 = readl(host->base + LCDC_VDCTRL3);
  1453. + vdctrl4 = readl(host->base + LCDC_VDCTRL4);
  1454.  
  1455. - transfer_count = readl(host->base + host->devdata->transfer_count);
  1456. + transfer_count = readl(host->base + host->devdata->transfer_count);
  1457.  
  1458. - vmode.xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
  1459. - vmode.yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
  1460. + vmode.xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
  1461. + vmode.yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
  1462.  
  1463. - switch (CTRL_GET_WORD_LENGTH(ctrl)) {
  1464. - case 0:
  1465. - bits_per_pixel = 16;
  1466. - break;
  1467. - case 3:
  1468. - bits_per_pixel = 32;
  1469. - break;
  1470. - case 1:
  1471. - default:
  1472. - return -EINVAL;
  1473. - }
  1474. + switch (CTRL_GET_WORD_LENGTH(ctrl)) {
  1475. + case 0:
  1476. + bits_per_pixel = 16;
  1477. + break;
  1478. + case 3:
  1479. + bits_per_pixel = 32;
  1480. + break;
  1481. + case 1:
  1482. + default:
  1483. + return -EINVAL;
  1484. + }
  1485.  
  1486. - fb_info->var.bits_per_pixel = bits_per_pixel;
  1487. + fb_info->var.bits_per_pixel = bits_per_pixel;
  1488.  
  1489. - vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk_pix) / 1000U);
  1490. - vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2);
  1491. - vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len;
  1492. - vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len -
  1493. - vmode.left_margin - vmode.xres;
  1494. - vmode.vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
  1495. - period = readl(host->base + LCDC_VDCTRL1);
  1496. - vmode.upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode.vsync_len;
  1497. - vmode.lower_margin = period - vmode.vsync_len - vmode.upper_margin - vmode.yres;
  1498. + vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk_pix) / 1000U);
  1499. + vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2);
  1500. + vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len;
  1501. + vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len -
  1502. + vmode.left_margin - vmode.xres;
  1503. + vmode.vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
  1504. + period = readl(host->base + LCDC_VDCTRL1);
  1505. + vmode.upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode.vsync_len;
  1506. + vmode.lower_margin = period - vmode.vsync_len - vmode.upper_margin - vmode.yres;
  1507.  
  1508. - vmode.vmode = FB_VMODE_NONINTERLACED;
  1509. + vmode.vmode = FB_VMODE_NONINTERLACED;
  1510.  
  1511. - vmode.sync = 0;
  1512. - if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
  1513. - vmode.sync |= FB_SYNC_HOR_HIGH_ACT;
  1514. - if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
  1515. - vmode.sync |= FB_SYNC_VERT_HIGH_ACT;
  1516. + vmode.sync = 0;
  1517. + if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
  1518. + vmode.sync |= FB_SYNC_HOR_HIGH_ACT;
  1519. + if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
  1520. + vmode.sync |= FB_SYNC_VERT_HIGH_ACT;
  1521.  
  1522. - pr_debug("Reconstructed video mode:\n");
  1523. - pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
  1524. - vmode.xres, vmode.yres,
  1525. - vmode.hsync_len, vmode.left_margin, vmode.right_margin,
  1526. - vmode.vsync_len, vmode.upper_margin, vmode.lower_margin);
  1527. - pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode.pixclock));
  1528. + pr_debug("Reconstructed video mode:\n");
  1529. + pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
  1530. + vmode.xres, vmode.yres,
  1531. + vmode.hsync_len, vmode.left_margin, vmode.right_margin,
  1532. + vmode.vsync_len, vmode.upper_margin, vmode.lower_margin);
  1533. + pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode.pixclock));
  1534.  
  1535. - fb_add_videomode(&vmode, &fb_info->modelist);
  1536. + fb_add_videomode(&vmode, &fb_info->modelist);
  1537.  
  1538. - host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
  1539. - host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
  1540. + host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
  1541. + host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
  1542.  
  1543. - fb_info->fix.line_length = vmode.xres * (bits_per_pixel >> 3);
  1544. + fb_info->fix.line_length = vmode.xres * (bits_per_pixel >> 3);
  1545.  
  1546. - pa = readl(host->base + host->devdata->cur_buf);
  1547. - fbsize = fb_info->fix.line_length * vmode.yres;
  1548. - if (pa < fb_info->fix.smem_start)
  1549. - return -EINVAL;
  1550. - if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
  1551. - return -EINVAL;
  1552. - ofs = pa - fb_info->fix.smem_start;
  1553. - if (ofs) {
  1554. - memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
  1555. - writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
  1556. - }
  1557. + pa = readl(host->base + host->devdata->cur_buf);
  1558. + fbsize = fb_info->fix.line_length * vmode.yres;
  1559. + if (pa < fb_info->fix.smem_start)
  1560. + return -EINVAL;
  1561. + if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
  1562. + return -EINVAL;
  1563. + ofs = pa - fb_info->fix.smem_start;
  1564. + if (ofs) {
  1565. + memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
  1566. + writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
  1567. + }
  1568.  
  1569. - line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
  1570. - fb_info->fix.ypanstep = 1;
  1571. - fb_info->fix.ywrapstep = 1;
  1572. + line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
  1573. + fb_info->fix.ypanstep = 1;
  1574. + fb_info->fix.ywrapstep = 1;
  1575.  
  1576. - host->enabled = 1;
  1577. + host->enabled = 1;
  1578. + }
  1579.  
  1580. return 0;
  1581. }
  1582. @@ -1290,6 +1470,7 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
  1583. const char *disp_dev, *disp_videomode;
  1584. u32 width;
  1585. int i;
  1586. + const char *lcd_panel;
  1587. int ret = 0;
  1588.  
  1589. host->id = of_alias_get_id(np, "lcdif");
  1590. @@ -1299,84 +1480,156 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
  1591. dev_err(dev, "failed to find display phandle\n");
  1592. return -ENOENT;
  1593. }
  1594. +
  1595. + host->is_mpu_lcd = of_property_read_bool(display_np, "mpu-mode");
  1596. + if (host->is_mpu_lcd) {
  1597. + struct fb_videomode *mpu_lcd_modedb;
  1598. + struct fb_videomode fb_vm;
  1599. + int size;
  1600.  
  1601. - ret = of_property_read_u32(display_np, "bus-width", &width);
  1602. - if (ret < 0) {
  1603. - dev_err(dev, "failed to get property bus-width\n");
  1604. - goto put_display_node;
  1605. - }
  1606. + ret = of_property_read_string(display_np, "lcd_panel", &lcd_panel);
  1607. + if (ret) {
  1608. + dev_err(dev, "failed to read of property lcd_panel\n");
  1609. + goto put_display_node;
  1610. + }
  1611.  
  1612. - switch (width) {
  1613. - case 8:
  1614. - host->ld_intf_width = STMLCDIF_8BIT;
  1615. - break;
  1616. - case 16:
  1617. - host->ld_intf_width = STMLCDIF_16BIT;
  1618. - break;
  1619. - case 18:
  1620. - host->ld_intf_width = STMLCDIF_18BIT;
  1621. - break;
  1622. - case 24:
  1623. - host->ld_intf_width = STMLCDIF_24BIT;
  1624. - break;
  1625. - default:
  1626. - dev_err(dev, "invalid bus-width value\n");
  1627. - ret = -EINVAL;
  1628. - goto put_display_node;
  1629. - }
  1630. + for (i = 0; i < ARRAY_SIZE(mpu_lcd_db); i++) {
  1631. + if (!strcmp(lcd_panel, mpu_lcd_db[i].lcd_panel)) {
  1632. + host->mpu_lcd_functions =
  1633. + &mpu_lcd_db[i].lcd_callback;
  1634. + break;
  1635. + }
  1636. + }
  1637. + if (i == ARRAY_SIZE(mpu_lcd_db)) {
  1638. + dev_err(dev, "failed to find supported lcd panel.\n");
  1639. + ret = -EINVAL;
  1640. + goto put_display_node;
  1641. + }
  1642. + host->mpu_lcd_functions->get_mpu_lcd_videomode(&mpu_lcd_modedb, &size,
  1643. + &host->mpu_lcd_sigs);
  1644.  
  1645. - ret = of_property_read_u32(display_np, "bits-per-pixel",
  1646. - &var->bits_per_pixel);
  1647. - if (ret < 0) {
  1648. - dev_err(dev, "failed to get property bits-per-pixel\n");
  1649. - goto put_display_node;
  1650. - }
  1651. + memcpy(&fb_vm, mpu_lcd_modedb, sizeof(struct fb_videomode));
  1652. + var->bits_per_pixel = host->mpu_lcd_sigs->panel_bpp;
  1653.  
  1654. - ret = of_property_read_string(np, "disp-dev", &disp_dev);
  1655. - if (!ret) {
  1656. - memcpy(host->disp_dev, disp_dev, strlen(disp_dev));
  1657. + switch (host->mpu_lcd_sigs->interface_width) {
  1658. + case 8:
  1659. + host->ld_intf_width = STMLCDIF_8BIT;
  1660. + break;
  1661. + case 16:
  1662. + host->ld_intf_width = STMLCDIF_16BIT;
  1663. + break;
  1664. + case 18:
  1665. + host->ld_intf_width = STMLCDIF_18BIT;
  1666. + break;
  1667. + case 24:
  1668. + host->ld_intf_width = STMLCDIF_24BIT;
  1669. + break;
  1670. + default:
  1671. + dev_err(dev, "invalid interface width value\n");
  1672. + ret = -EINVAL;
  1673. + goto put_display_node;
  1674. + }
  1675.  
  1676. - if (!of_property_read_string(np, "disp-videomode",
  1677. - &disp_videomode)) {
  1678. - memcpy(host->disp_videomode, disp_videomode,
  1679. - strlen(disp_videomode));
  1680. + /* lcd reset gpio pin */
  1681. + host->mpu_lcd_sigs->lcd_reset_is_gpio = 0;
  1682. + host->mpu_lcd_sigs->lcd_reset_gpio = of_get_named_gpio(display_np, "lcd_reset_gpio", 0);
  1683. + if (gpio_is_valid(host->mpu_lcd_sigs->lcd_reset_gpio)) {
  1684. + dev_info(dev, "find lcd reset gpio pin.\n");
  1685. + if (devm_gpio_request_one(dev, host->mpu_lcd_sigs->lcd_reset_gpio, GPIOF_OUT_INIT_HIGH, "lcd_reset") >= 0)
  1686. + host->mpu_lcd_sigs->lcd_reset_is_gpio = 1;
  1687. }
  1688.  
  1689. - /* Timing is from encoder driver */
  1690. - goto put_display_node;
  1691. - }
  1692. + /* lcd rs gpio pin */
  1693. + host->mpu_lcd_sigs->lcd_rs_is_gpio = 0;
  1694. + host->mpu_lcd_sigs->lcd_rs_gpio = of_get_named_gpio(display_np, "lcd_rs_gpio", 0);
  1695. + if (gpio_is_valid(host->mpu_lcd_sigs->lcd_rs_gpio)) {
  1696. + dev_info(dev, "find lcd rs gpio pin.\n");
  1697. + if (devm_gpio_request_one(dev, host->mpu_lcd_sigs->lcd_rs_is_gpio, GPIOF_OUT_INIT_HIGH, "lcd_rs") >= 0)
  1698. + host->mpu_lcd_sigs->lcd_rs_is_gpio = 1;
  1699. + }
  1700.  
  1701. - timings = of_get_display_timings(display_np);
  1702. - if (!timings) {
  1703. - dev_err(dev, "failed to get display timings\n");
  1704. - ret = -ENOENT;
  1705. - goto put_display_node;
  1706. - }
  1707. + fb_add_videomode(&fb_vm, &fb_info->modelist);
  1708. + goto put_display_node;
  1709. + } else {
  1710.  
  1711. - timings_np = of_find_node_by_name(display_np,
  1712. - "display-timings");
  1713. - if (!timings_np) {
  1714. - dev_err(dev, "failed to find display-timings node\n");
  1715. - ret = -ENOENT;
  1716. - goto put_display_node;
  1717. - }
  1718. + ret = of_property_read_u32(display_np, "bus-width", &width);
  1719. + if (ret < 0) {
  1720. + dev_err(dev, "failed to get property bus-width\n");
  1721. + goto put_display_node;
  1722. + }
  1723.  
  1724. - for (i = 0; i < of_get_child_count(timings_np); i++) {
  1725. - struct videomode vm;
  1726. - struct fb_videomode fb_vm;
  1727. + switch (width) {
  1728. + case 8:
  1729. + host->ld_intf_width = STMLCDIF_8BIT;
  1730. + break;
  1731. + case 16:
  1732. + host->ld_intf_width = STMLCDIF_16BIT;
  1733. + break;
  1734. + case 18:
  1735. + host->ld_intf_width = STMLCDIF_18BIT;
  1736. + break;
  1737. + case 24:
  1738. + host->ld_intf_width = STMLCDIF_24BIT;
  1739. + break;
  1740. + default:
  1741. + dev_err(dev, "invalid bus-width value\n");
  1742. + ret = -EINVAL;
  1743. + goto put_display_node;
  1744. + }
  1745.  
  1746. - ret = videomode_from_timings(timings, &vm, i);
  1747. - if (ret < 0)
  1748. - goto put_timings_node;
  1749. - ret = fb_videomode_from_videomode(&vm, &fb_vm);
  1750. - if (ret < 0)
  1751. - goto put_timings_node;
  1752. + ret = of_property_read_u32(display_np, "bits-per-pixel",
  1753. + &var->bits_per_pixel);
  1754. + if (ret < 0) {
  1755. + dev_err(dev, "failed to get property bits-per-pixel\n");
  1756. + goto put_display_node;
  1757. + }
  1758.  
  1759. - if (!(vm.flags & DISPLAY_FLAGS_DE_HIGH))
  1760. - fb_vm.sync |= FB_SYNC_OE_LOW_ACT;
  1761. - if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
  1762. - fb_vm.sync |= FB_SYNC_CLK_LAT_FALL;
  1763. - fb_add_videomode(&fb_vm, &fb_info->modelist);
  1764. + ret = of_property_read_string(np, "disp-dev", &disp_dev);
  1765. + if (!ret) {
  1766. + memcpy(host->disp_dev, disp_dev, strlen(disp_dev));
  1767. +
  1768. + if (!of_property_read_string(np, "disp-videomode",
  1769. + &disp_videomode)) {
  1770. + memcpy(host->disp_videomode, disp_videomode,
  1771. + strlen(disp_videomode));
  1772. + }
  1773. +
  1774. + /* Timing is from encoder driver */
  1775. + goto put_display_node;
  1776. + }
  1777. +
  1778. + timings = of_get_display_timings(display_np);
  1779. + if (!timings) {
  1780. + dev_err(dev, "failed to get display timings\n");
  1781. + ret = -ENOENT;
  1782. + goto put_display_node;
  1783. + }
  1784. +
  1785. + timings_np = of_find_node_by_name(display_np,
  1786. + "display-timings");
  1787. + if (!timings_np) {
  1788. + dev_err(dev, "failed to find display-timings node\n");
  1789. + ret = -ENOENT;
  1790. + goto put_display_node;
  1791. + }
  1792. +
  1793. + for (i = 0; i < of_get_child_count(timings_np); i++) {
  1794. + struct videomode vm;
  1795. + struct fb_videomode fb_vm;
  1796. +
  1797. + ret = videomode_from_timings(timings, &vm, i);
  1798. + if (ret < 0)
  1799. + goto put_timings_node;
  1800. + ret = fb_videomode_from_videomode(&vm, &fb_vm);
  1801. + if (ret < 0)
  1802. + goto put_timings_node;
  1803. +
  1804. + if (!(vm.flags & DISPLAY_FLAGS_DE_HIGH))
  1805. + fb_vm.sync |= FB_SYNC_OE_LOW_ACT;
  1806. + if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
  1807. + fb_vm.sync |= FB_SYNC_CLK_LAT_FALL;
  1808. + fb_add_videomode(&fb_vm, &fb_info->modelist);
  1809. + }
  1810. }
  1811.  
  1812. put_timings_node:
  1813. @@ -2309,8 +2562,13 @@ static int mxsfb_probe(struct platform_device *pdev)
  1814.  
  1815. if (!host->enabled) {
  1816. writel(0, host->base + LCDC_CTRL);
  1817. - mxsfb_set_par(fb_info);
  1818. - mxsfb_enable_controller(fb_info);
  1819. + if (host->is_mpu_lcd) {
  1820. + mxsfb_enable_controller(fb_info);
  1821. + mxsfb_set_par(host->fb_info);
  1822. + } else {
  1823. + mxsfb_set_par(host->fb_info);
  1824. + mxsfb_enable_controller(fb_info);
  1825. + }
  1826. pm_runtime_get_sync(&host->pdev->dev);
  1827. }
  1828.  
  1829. @@ -2388,6 +2646,8 @@ static void mxsfb_shutdown(struct platform_device *pdev)
  1830. if (host->cur_blank == FB_BLANK_UNBLANK) {
  1831. writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
  1832. writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_CLR);
  1833. + if (host->is_mpu_lcd)
  1834. + host->mpu_lcd_functions->mpu_lcd_poweroff(host);
  1835. }
  1836. }
  1837.  
  1838. @@ -2447,7 +2707,9 @@ static int mxsfb_resume(struct device *pdev)
  1839. struct mxsfb_info *host = dev_get_drvdata(pdev);
  1840. struct fb_info *fb_info = host->fb_info;
  1841.  
  1842. - pinctrl_pm_select_default_state(pdev);
  1843. + // TODO: Watch this, this looks like an infinite recursive loop...
  1844. + // - pinctrl_pm_select_default_state(pdev);
  1845. + mxsfb_resume(pdev);
  1846.  
  1847. console_lock();
  1848. mxsfb_blank(host->restore_blank, fb_info);
  1849. diff --git a/drivers/video/fbdev/mxsfb.h b/drivers/video/fbdev/mxsfb.h
  1850. new file mode 100644
  1851. index 000000000000..822d4ebb9cc9
  1852. --- /dev/null
  1853. +++ b/drivers/video/fbdev/mxsfb.h
  1854. @@ -0,0 +1,371 @@
  1855. +/*
  1856. +* Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
  1857. +*
  1858. +* This program is free software; you can redistribute it and/or modify
  1859. +* it under the terms of the GNU General Public License as published by
  1860. +* the Free Software Foundation; either version 2 of the License, or
  1861. +* (at your option) any later version.
  1862. +
  1863. +* This program is distributed in the hope that it will be useful,
  1864. +* but WITHOUT ANY WARRANTY; without even the implied warranty of
  1865. +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1866. +* GNU General Public License for more details.
  1867. +
  1868. +* You should have received a copy of the GNU General Public License along
  1869. +* with this program; if not, write to the Free Software Foundation, Inc.,
  1870. +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  1871. +*/
  1872. +
  1873. +#ifndef __MXSFB_H__
  1874. +#define __MXSFB_H__
  1875. +
  1876. +#include <linux/regmap.h>
  1877. +#include <linux/platform_device.h>
  1878. +#include <linux/fb.h>
  1879. +#include <linux/mxcfb.h>
  1880. +#include <linux/pm_qos.h>
  1881. +
  1882. +#define REG_SET 4
  1883. +#define REG_CLR 8
  1884. +
  1885. +#define LCDC_CTRL 0x00
  1886. +#define LCDC_CTRL1 0x10
  1887. +#define LCDC_V4_CTRL2 0x20
  1888. +#define LCDC_V3_TRANSFER_COUNT 0x20
  1889. +#define LCDC_V4_TRANSFER_COUNT 0x30
  1890. +#define LCDC_V4_CUR_BUF 0x40
  1891. +#define LCDC_V4_NEXT_BUF 0x50
  1892. +#define LCDC_V3_CUR_BUF 0x30
  1893. +#define LCDC_V3_NEXT_BUF 0x40
  1894. +#define LCDC_TIMING 0x60
  1895. +#define LCDC_VDCTRL0 0x70
  1896. +#define LCDC_VDCTRL1 0x80
  1897. +#define LCDC_VDCTRL2 0x90
  1898. +#define LCDC_VDCTRL3 0xa0
  1899. +#define LCDC_VDCTRL4 0xb0
  1900. +#define LCDC_DVICTRL0 0xc0
  1901. +#define LCDC_DVICTRL1 0xd0
  1902. +#define LCDC_DVICTRL2 0xe0
  1903. +#define LCDC_DVICTRL3 0xf0
  1904. +#define LCDC_DVICTRL4 0x100
  1905. +#define LCDC_V4_DATA 0x180
  1906. +#define LCDC_V3_DATA 0x1b0
  1907. +#define LCDC_V4_DEBUG0 0x1d0
  1908. +#define LCDC_V3_DEBUG0 0x1f0
  1909. +#define LCDC_AS_CTRL 0x210
  1910. +#define LCDC_AS_BUF 0x220
  1911. +#define LCDC_AS_NEXT_BUF 0x230
  1912. +
  1913. +#define CTRL_SFTRST (1 << 31)
  1914. +#define CTRL_CLKGATE (1 << 30)
  1915. +#define CTRL_YCBCR422_INPUT (1 << 29)
  1916. +#define CTRL_READ_WRITEB (1 << 28)
  1917. +#define CTRL_WAIT_FOR_VSYNC_EDGE (1 << 27)
  1918. +#define CTRL_DATA_SHIFT_DIR (1 << 26)
  1919. +#define CTRL_SHIFT_NUM_BITS_MASK (0x1f << 21)
  1920. +#define CTRL_SHIFT_NUM_BITS_OFFSET 21
  1921. +#define CTRL_DVI_MODE (1 << 20)
  1922. +#define CTRL_BYPASS_COUNT (1 << 19)
  1923. +#define CTRL_VSYNC_MODE (1 << 18)
  1924. +#define CTRL_DOTCLK_MODE (1 << 17)
  1925. +#define CTRL_DATA_SELECT (1 << 16)
  1926. +#define CTRL_INPUT_DATA_SWIZZLE_MASK (0x3 << 14)
  1927. +#define CTRL_INPUT_DATA_SWIZZLE_OFFSET 14
  1928. +#define CTRL_CSC_DATA_SWIZZLE_MASK (0x3 << 12)
  1929. +#define CTRL_CSC_DATA_SWIZZLE_OFFSET 12
  1930. +#define CTRL_LCD_DATABUS_WIDTH_MASK (0x3 << 10)
  1931. +#define CTRL_LCD_DATABUS_WIDTH_OFFSET 10
  1932. +#define CTRL_LCD_DATABUS_WIDTH_16BIT (0 << 10)
  1933. +#define CTRL_LCD_DATABUS_WIDTH_8BIT (1 << 10)
  1934. +#define CTRL_LCD_DATABUS_WIDTH_18BIT (2 << 10)
  1935. +#define CTRL_LCD_DATABUS_WIDTH_24BIT (3 << 10)
  1936. +#define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10)
  1937. +#define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3)
  1938. +#define CTRL_WORD_LENGTH_MASK (0x3 << 8)
  1939. +#define CTRL_WORD_LENGTH_OFFSET 8
  1940. +#define CTRL_WORD_LENGTH_16BIT (0 << 8)
  1941. +#define CTRL_WORD_LENGTH_8BIT (1 << 8)
  1942. +#define CTRL_WORD_LENGTH_18BIT (2 << 8)
  1943. +#define CTRL_WORD_LENGTH_24BIT (3 << 8)
  1944. +#define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8)
  1945. +#define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3)
  1946. +#define CTRL_RGB_TO_YCBCR422_CSC (1 << 7)
  1947. +#define CTRL_MASTER (1 << 5)
  1948. +#define CTRL_DATA_FORMAT_16_BIT (1 << 3)
  1949. +#define CTRL_DATA_FORMAT_18_BIT (1 << 2)
  1950. +#define CTRL_DATA_FORMAT_24_BIT (1 << 1)
  1951. +#define CTRL_RUN (1 << 0)
  1952. +
  1953. +#define CTRL1_COMBINE_MPU_WR_STRB (1 << 27)
  1954. +#define CTRL1_BM_ERROR_IRQ_EN (1 << 26)
  1955. +#define CTRL1_BM_ERROR_IRQ (1 << 25)
  1956. +#define CTRL1_RECOVERY_ON_UNDERFLOW (1 << 24)
  1957. +#define CTRL1_INTERLACE_FIELDS (1 << 23)
  1958. +#define CTRL1_START_INTERLACE_FROM_SECOND_FIELD (1 << 22)
  1959. +#define CTRL1_FIFO_CLEAR (1 << 21)
  1960. +#define CTRL1_IRQ_ON_ALTERNATE_FIELDS (1 << 20)
  1961. +#define CTRL1_BYTE_PACKING_FORMAT_MASK (0xf << 16)
  1962. +#define CTRL1_BYTE_PACKING_FORMAT_OFFSET 16
  1963. +#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
  1964. +#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
  1965. +#define CTRL1_OVERFLOW_IRQ_EN (1 << 15)
  1966. +#define CTRL1_UNDERFLOW_IRQ_EN (1 << 14)
  1967. +#define CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13)
  1968. +#define CTRL1_VSYNC_EDGE_IRQ_EN (1 << 12)
  1969. +#define CTRL1_OVERFLOW_IRQ (1 << 11)
  1970. +#define CTRL1_UNDERFLOW_IRQ (1 << 10)
  1971. +#define CTRL1_CUR_FRAME_DONE_IRQ (1 << 9)
  1972. +#define CTRL1_VSYNC_EDGE_IRQ (1 << 8)
  1973. +#define CTRL1_BUSY_ENABLE (1 << 2)
  1974. +#define CTRL1_MODE86 (1 << 1)
  1975. +#define CTRL1_RESET (1 << 0)
  1976. +#define CTRL1_IRQ_ENABLE_MASK (CTRL1_OVERFLOW_IRQ_EN | \
  1977. + CTRL1_UNDERFLOW_IRQ_EN | \
  1978. + CTRL1_CUR_FRAME_DONE_IRQ_EN | \
  1979. + CTRL1_VSYNC_EDGE_IRQ_EN)
  1980. +#define CTRL1_IRQ_ENABLE_SHIFT 12
  1981. +#define CTRL1_IRQ_STATUS_MASK (CTRL1_OVERFLOW_IRQ | \
  1982. + CTRL1_UNDERFLOW_IRQ | \
  1983. + CTRL1_CUR_FRAME_DONE_IRQ | \
  1984. + CTRL1_VSYNC_EDGE_IRQ)
  1985. +#define CTRL1_IRQ_STATUS_SHIFT 8
  1986. +
  1987. +#define CTRL2_OUTSTANDING_REQS_MASK (0x7 << 21)
  1988. +#define CTRL2_OUTSTANDING_REQS_OFFSET 21
  1989. +#define CTRL2_OUTSTANDING_REQS_REQ_1 (0x0 << 21)
  1990. +#define CTRL2_OUTSTANDING_REQS_REQ_2 (0x1 << 21)
  1991. +#define CTRL2_OUTSTANDING_REQS_REQ_4 (0x2 << 21)
  1992. +#define CTRL2_OUTSTANDING_REQS_REQ_8 (0x3 << 21)
  1993. +#define CTRL2_OUTSTANDING_REQS_REQ_16 (0x4 << 21)
  1994. +#define CTRL2_BURST_LEN_8 (1 << 20)
  1995. +#define CTRL2_ODD_LINE_PATTERN_MASK (0x7 << 16)
  1996. +#define CTRL2_ODD_LINE_PATTERN_OFFSET 16
  1997. +#define CTRL2_ODD_LINE_PATTERN_RGB (0x0 << 16)
  1998. +#define CTRL2_ODD_LINE_PATTERN_RBG (0x1 << 16)
  1999. +#define CTRL2_ODD_LINE_PATTERN_GBR (0x2 << 16)
  2000. +#define CTRL2_ODD_LINE_PATTERN_GRB (0x3 << 16)
  2001. +#define CTRL2_ODD_LINE_PATTERN_BRG (0x4 << 16)
  2002. +#define CTRL2_ODD_LINE_PATTERN_BGR (0x5 << 16)
  2003. +#define CTRL2_EVEN_LINE_PATTERN_MASK (0x7 << 12)
  2004. +#define CTRL2_EVEN_LINE_PATTERN_OFFSET 12
  2005. +#define CTRL2_EVEN_LINE_PATTERN_RGB (0x0 << 12)
  2006. +#define CTRL2_EVEN_LINE_PATTERN_RBG (0x1 << 12)
  2007. +#define CTRL2_EVEN_LINE_PATTERN_GBR (0x2 << 12)
  2008. +#define CTRL2_EVEN_LINE_PATTERN_GRB (0x3 << 12)
  2009. +#define CTRL2_EVEN_LINE_PATTERN_BRG (0x4 << 12)
  2010. +#define CTRL2_EVEN_LINE_PATTERN_BGR (0x5 << 12)
  2011. +#define CTRL2_READ_PACK_DIR (1 << 10)
  2012. +#define CTRL2_READ_MODE_OUTPUT_IN_RGB_FORMAT (1 << 9)
  2013. +#define CTRL2_READ_MODE_6_BIT_INPUT (1 << 8)
  2014. +#define CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_MASK (0x7 << 4)
  2015. +#define CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_OFFSET 4
  2016. +#define CTRL2_INITIAL_DUMMY_READ_MASK (0x7 << 1)
  2017. +#define CTRL2_INITIAL_DUMMY_READ_OFFSET 1
  2018. +
  2019. +#define TRANSFER_COUNT_V_COUNT_MASK (0xffff << 16)
  2020. +#define TRANSFER_COUNT_V_COUNT_OFFSET 16
  2021. +#define TRANSFER_COUNT_H_COUNT_MASK (0xffff << 0)
  2022. +#define TRANSFER_COUNT_H_COUNT_OFFSET 0
  2023. +#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
  2024. +#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
  2025. +#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)
  2026. +#define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff)
  2027. +
  2028. +#define CUR_BUF_ADDR_MASK 0xffffffff
  2029. +#define CUR_BUF_ADDR_OFFSET 0
  2030. +
  2031. +#define NEXT_BUF_ADDR_MASK 0xffffffff
  2032. +#define NEXT_BUF_ADDR_OFFSET 0
  2033. +
  2034. +#define TIMING_CMD_HOLD_MASK (0xff << 24)
  2035. +#define TIMING_CMD_HOLD_OFFSET 24
  2036. +#define TIMING_CMD_SETUP_MASK (0xff << 16)
  2037. +#define TIMING_CMD_SETUP_OFFSET 16
  2038. +#define TIMING_DATA_HOLD_MASK (0xff << 8)
  2039. +#define TIMING_DATA_HOLD_OFFSET 8
  2040. +#define TIMING_DATA_SETUP_MASK (0xff << 0)
  2041. +#define TIMING_DATA_SETUP_OFFSET 0
  2042. +
  2043. +#define VDCTRL0_VSYNC_OEB (1 << 29)
  2044. +#define VDCTRL0_ENABLE_PRESENT (1 << 28)
  2045. +#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
  2046. +#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
  2047. +#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25)
  2048. +#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24)
  2049. +#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
  2050. +#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
  2051. +#define VDCTRL0_HALF_LINE (1 << 19)
  2052. +#define VDCTRL0_HALF_LINE_MODE (1 << 18)
  2053. +#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
  2054. +#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
  2055. +
  2056. +#define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
  2057. +#define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
  2058. +
  2059. +#define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29)
  2060. +#define VDCTRL3_VSYNC_ONLY (1 << 28)
  2061. +#define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16)
  2062. +#define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff)
  2063. +#define SET_VERT_WAIT_CNT(x) ((x) & 0xffff)
  2064. +#define GET_VERT_WAIT_CNT(x) ((x) & 0xffff)
  2065. +
  2066. +#define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */
  2067. +#define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */
  2068. +#define VDCTRL4_SYNC_SIGNALS_ON (1 << 18)
  2069. +#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
  2070. +
  2071. +#define DEBUG0_HSYNC (1 < 26)
  2072. +#define DEBUG0_VSYNC (1 < 25)
  2073. +
  2074. +#define MIN_XRES 120
  2075. +#define MIN_YRES 120
  2076. +
  2077. +#define RED 0
  2078. +#define GREEN 1
  2079. +#define BLUE 2
  2080. +#define TRANSP 3
  2081. +
  2082. +#define STMLCDIF_8BIT 1 /** pixel data bus to the display is of 8 bit width */
  2083. +#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
  2084. +#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
  2085. +#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
  2086. +
  2087. +#define FB_SYNC_OE_LOW_ACT 0x80000000
  2088. +#define FB_SYNC_CLK_LAT_FALL 0x40000000
  2089. +
  2090. +enum mxsfb_devtype {
  2091. + MXSFB_V3,
  2092. + MXSFB_V4,
  2093. + MXSFB_V5,
  2094. +};
  2095. +
  2096. +enum {
  2097. + MPU_DATA,
  2098. + MPU_CMD,
  2099. +};
  2100. +
  2101. +enum {
  2102. + MPU_READ,
  2103. + MPU_WRITE,
  2104. +};
  2105. +
  2106. +enum {
  2107. + MPU_BUS_8080,
  2108. + MPU_BUS_6800,
  2109. +};
  2110. +
  2111. +struct mpu_lcd_config {
  2112. + u32 bus_mode;
  2113. + u32 interface_width;
  2114. + u32 panel_bpp;
  2115. + bool lcd_reset_is_gpio;
  2116. + int lcd_reset_gpio;
  2117. + bool lcd_rs_is_gpio;
  2118. + int lcd_rs_gpio;
  2119. +};
  2120. +
  2121. +/* CPU dependent register offsets */
  2122. +struct mxsfb_devdata {
  2123. + unsigned transfer_count;
  2124. + unsigned data;
  2125. + unsigned cur_buf;
  2126. + unsigned next_buf;
  2127. + unsigned debug0;
  2128. + unsigned hs_wdth_mask;
  2129. + unsigned hs_wdth_shift;
  2130. + unsigned ipversion;
  2131. + u32 flags;
  2132. +};
  2133. +
  2134. +struct mxsfb_layer;
  2135. +
  2136. +struct mxsfb_layer_ops {
  2137. + void (*enable)(struct mxsfb_layer *ofb);
  2138. + void (*disable)(struct mxsfb_layer *ofb);
  2139. + void (*setup)(struct mxsfb_layer *ofb);
  2140. +};
  2141. +
  2142. +struct mxsfb_layer {
  2143. + struct fb_info *ol_fb;
  2144. + int id;
  2145. + int registered;
  2146. + atomic_t usage;
  2147. + int blank_state;
  2148. + uint32_t global_alpha;
  2149. +
  2150. + struct mxsfb_layer_ops *ops;
  2151. +
  2152. + struct device *dev;
  2153. + void __iomem *video_mem;
  2154. + unsigned long video_mem_phys;
  2155. + size_t video_mem_size;
  2156. +
  2157. + struct mxsfb_info *fbi;
  2158. +};
  2159. +
  2160. +#define NAME_LEN 32
  2161. +
  2162. +struct mxsfb_info;
  2163. +
  2164. +struct mpu_lcd_callback {
  2165. + /* callback for lcd panel operation */
  2166. + void (*get_mpu_lcd_videomode)(struct fb_videomode **, int *,
  2167. + struct mpu_lcd_config **);
  2168. + int (*mpu_lcd_setup)(struct mxsfb_info *);
  2169. + int (*mpu_lcd_poweroff)(struct mxsfb_info *);
  2170. +};
  2171. +
  2172. +struct mpu_match_lcd {
  2173. + char *lcd_panel;
  2174. + struct mpu_lcd_callback lcd_callback;
  2175. +};
  2176. +
  2177. +struct mxsfb_info {
  2178. + struct fb_info *fb_info;
  2179. + struct platform_device *pdev;
  2180. + struct clk *clk_pix;
  2181. + struct clk *clk_axi;
  2182. + struct clk *clk_disp_axi;
  2183. + bool clk_pix_enabled;
  2184. + bool clk_axi_enabled;
  2185. + bool clk_disp_axi_enabled;
  2186. + void __iomem *base; /* registers */
  2187. + u32 sync; /* record display timing polarities */
  2188. + unsigned allocated_size;
  2189. + int enabled;
  2190. + unsigned ld_intf_width;
  2191. + unsigned dotclk_delay;
  2192. + const struct mxsfb_devdata *devdata;
  2193. + struct regulator *reg_lcd;
  2194. + bool wait4vsync;
  2195. + struct completion vsync_complete;
  2196. + struct completion flip_complete;
  2197. + int cur_blank;
  2198. + int restore_blank;
  2199. + char disp_dev[NAME_LEN];
  2200. + struct mxc_dispdrv_handle *dispdrv;
  2201. + int id;
  2202. + struct fb_var_screeninfo var;
  2203. + struct pm_qos_request pm_qos_req;
  2204. +
  2205. + char disp_videomode[NAME_LEN];
  2206. +
  2207. + bool is_mpu_lcd;
  2208. + struct mpu_lcd_config * mpu_lcd_sigs;
  2209. + struct mpu_lcd_callback * mpu_lcd_functions;
  2210. +
  2211. +#ifdef CONFIG_FB_MXC_OVERLAY
  2212. + struct mxsfb_layer overlay;
  2213. +#endif
  2214. +};
  2215. +
  2216. +unsigned int mxsfb_mpu_access(struct mxsfb_info *host, int mode, int rw, int data);
  2217. +
  2218. +#ifdef CONFIG_FB_MXS_ST7789S_QVGA
  2219. +void mpu_st7789s_get_lcd_videomode(struct fb_videomode **mode, int *size,
  2220. + struct mpu_lcd_config **data);
  2221. +int mpu_st7789s_lcd_setup(struct mxsfb_info * mxsfb);
  2222. +int mpu_st7789s_lcd_poweroff(struct mxsfb_info * mxsfb);
  2223. +#endif
  2224. +
  2225. +#endif
  2226. diff --git a/include/uapi/linux/mxcfb.h b/include/uapi/linux/mxcfb.h
  2227. index 3a984090769a..c05b486c4dcb 100644
  2228. --- a/include/uapi/linux/mxcfb.h
  2229. +++ b/include/uapi/linux/mxcfb.h
  2230. @@ -182,6 +182,9 @@ struct mxcfb_csc_matrix {
  2231. #define MXCFB_SET_GPU_SPLIT_FMT _IOW('F', 0x2F, struct mxcfb_gpu_split_fmt)
  2232. #define MXCFB_SET_PREFETCH _IOW('F', 0x30, int)
  2233. #define MXCFB_GET_PREFETCH _IOR('F', 0x31, int)
  2234. +
  2235. +/* IOCTLs for mpu panel updates */
  2236. +#define MXCFB_MPU_REFRESH_PANEL _IOW('F', 0x33, u_int32_t)
  2237.  
  2238. /* IOCTLs for E-ink panel updates */
  2239. #define MXCFB_SET_WAVEFORM_MODES _IOW('F', 0x2B, struct mxcfb_waveform_modes)
  2240. --
  2241. 2.19.1
RAW Paste Data