Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'drm-next/mxsfb' of git://git.kernel.org/pub/scm/linux/kernel/git/marex/linux-2.6 into drm-next

Add new driver for MXSFB.

* 'drm-next/mxsfb' of git://git.kernel.org/pub/scm/linux/kernel/git/marex/linux-2.6:
drm: Add new driver for MXSFB controller
dt-bindings: mxsfb: Add new bindings for the MXSFB driver
dt-bindings: mxsfb: Indentation cleanup

+1058 -8
+45 -8
Documentation/devicetree/bindings/display/mxsfb.txt
··· 1 1 * Freescale MXS LCD Interface (LCDIF) 2 2 3 + New bindings: 4 + ============= 3 5 Required properties: 4 - - compatible: Should be "fsl,<chip>-lcdif". Supported chips include 5 - imx23 and imx28. 6 - - reg: Address and length of the register set for lcdif 7 - - interrupts: Should contain lcdif interrupts 8 - - display : phandle to display node (see below for details) 6 + - compatible: Should be "fsl,imx23-lcdif" for i.MX23. 7 + Should be "fsl,imx28-lcdif" for i.MX28. 8 + Should be "fsl,imx6sx-lcdif" for i.MX6SX. 9 + - reg: Address and length of the register set for LCDIF 10 + - interrupts: Should contain LCDIF interrupt 11 + - clocks: A list of phandle + clock-specifier pairs, one for each 12 + entry in 'clock-names'. 13 + - clock-names: A list of clock names. For MXSFB it should contain: 14 + - "pix" for the LCDIF block clock 15 + - (MX6SX-only) "axi", "disp_axi" for the bus interface clock 16 + 17 + Required sub-nodes: 18 + - port: The connection to an encoder chip. 19 + 20 + Example: 21 + 22 + lcdif1: display-controller@2220000 { 23 + compatible = "fsl,imx6sx-lcdif", "fsl,imx28-lcdif"; 24 + reg = <0x02220000 0x4000>; 25 + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; 26 + clocks = <&clks IMX6SX_CLK_LCDIF1_PIX>, 27 + <&clks IMX6SX_CLK_LCDIF_APB>, 28 + <&clks IMX6SX_CLK_DISPLAY_AXI>; 29 + clock-names = "pix", "axi", "disp_axi"; 30 + 31 + port { 32 + parallel_out: endpoint { 33 + remote-endpoint = <&panel_in_parallel>; 34 + }; 35 + }; 36 + }; 37 + 38 + Deprecated bindings: 39 + ==================== 40 + Required properties: 41 + - compatible: Should be "fsl,imx23-lcdif" for i.MX23. 42 + Should be "fsl,imx28-lcdif" for i.MX28. 43 + - reg: Address and length of the register set for LCDIF 44 + - interrupts: Should contain LCDIF interrupts 45 + - display: phandle to display node (see below for details) 9 46 10 47 * display node 11 48 12 49 Required properties: 13 - - bits-per-pixel : <16> for RGB565, <32> for RGB888/666. 14 - - bus-width : number of data lines. Could be <8>, <16>, <18> or <24>. 50 + - bits-per-pixel: <16> for RGB565, <32> for RGB888/666. 51 + - bus-width: number of data lines. Could be <8>, <16>, <18> or <24>. 15 52 16 53 Required sub-node: 17 - - display-timings : Refer to binding doc display-timing.txt for details. 54 + - display-timings: Refer to binding doc display-timing.txt for details. 18 55 19 56 Examples: 20 57
+6
MAINTAINERS
··· 8319 8319 S: Maintained 8320 8320 F: drivers/media/tuners/mxl5007t.* 8321 8321 8322 + MXSFB DRM DRIVER 8323 + M: Marek Vasut <marex@denx.de> 8324 + S: Supported 8325 + F: drivers/gpu/drm/mxsfb/ 8326 + F: Documentation/devicetree/bindings/display/mxsfb-drm.txt 8327 + 8322 8328 MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE) 8323 8329 M: Hyong-Youb Kim <hykim@myri.com> 8324 8330 L: netdev@vger.kernel.org
+2
drivers/gpu/drm/Kconfig
··· 240 240 241 241 source "drivers/gpu/drm/zte/Kconfig" 242 242 243 + source "drivers/gpu/drm/mxsfb/Kconfig" 244 + 243 245 # Keep legacy drivers last 244 246 245 247 menuconfig DRM_LEGACY
+1
drivers/gpu/drm/Makefile
··· 89 89 obj-$(CONFIG_DRM_ARCPGU)+= arc/ 90 90 obj-y += hisilicon/ 91 91 obj-$(CONFIG_DRM_ZTE) += zte/ 92 + obj-$(CONFIG_DRM_MXSFB) += mxsfb/
+18
drivers/gpu/drm/mxsfb/Kconfig
··· 1 + config DRM_MXS 2 + bool 3 + help 4 + Choose this option to select drivers for MXS FB devices 5 + 6 + config DRM_MXSFB 7 + tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller" 8 + depends on DRM && OF 9 + depends on COMMON_CLK 10 + select DRM_MXS 11 + select DRM_KMS_HELPER 12 + select DRM_KMS_FB_HELPER 13 + select DRM_KMS_CMA_HELPER 14 + help 15 + Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB 16 + LCD controller. 17 + 18 + If M is selected the module will be called mxsfb.
+2
drivers/gpu/drm/mxsfb/Makefile
··· 1 + mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o 2 + obj-$(CONFIG_DRM_MXSFB) += mxsfb.o
+241
drivers/gpu/drm/mxsfb/mxsfb_crtc.c
··· 1 + /* 2 + * Copyright (C) 2016 Marek Vasut <marex@denx.de> 3 + * 4 + * This code is based on drivers/video/fbdev/mxsfb.c : 5 + * Copyright (C) 2010 Juergen Beisert, Pengutronix 6 + * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. 7 + * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License 11 + * as published by the Free Software Foundation; either version 2 12 + * of the License, or (at your option) any later version. 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + */ 18 + 19 + #include <drm/drmP.h> 20 + #include <drm/drm_atomic_helper.h> 21 + #include <drm/drm_crtc.h> 22 + #include <drm/drm_crtc_helper.h> 23 + #include <drm/drm_fb_helper.h> 24 + #include <drm/drm_fb_cma_helper.h> 25 + #include <drm/drm_gem_cma_helper.h> 26 + #include <drm/drm_of.h> 27 + #include <drm/drm_plane_helper.h> 28 + #include <drm/drm_simple_kms_helper.h> 29 + #include <linux/clk.h> 30 + #include <linux/iopoll.h> 31 + #include <linux/of_graph.h> 32 + #include <linux/platform_data/simplefb.h> 33 + #include <video/videomode.h> 34 + 35 + #include "mxsfb_drv.h" 36 + #include "mxsfb_regs.h" 37 + 38 + static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val) 39 + { 40 + return (val & mxsfb->devdata->hs_wdth_mask) << 41 + mxsfb->devdata->hs_wdth_shift; 42 + } 43 + 44 + /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */ 45 + static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) 46 + { 47 + struct drm_crtc *crtc = &mxsfb->pipe.crtc; 48 + struct drm_device *drm = crtc->dev; 49 + const u32 format = crtc->primary->state->fb->pixel_format; 50 + u32 ctrl, ctrl1; 51 + 52 + ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER; 53 + 54 + /* 55 + * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to 56 + * match the selected mode here. This differs from the original 57 + * MXSFB driver, which had the option to configure the bus width 58 + * to arbitrary value. This limitation should not pose an issue. 59 + */ 60 + 61 + /* CTRL1 contains IRQ config and status bits, preserve those. */ 62 + ctrl1 = readl(mxsfb->base + LCDC_CTRL1); 63 + ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ; 64 + 65 + switch (format) { 66 + case DRM_FORMAT_RGB565: 67 + dev_dbg(drm->dev, "Setting up RGB565 mode\n"); 68 + ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT); 69 + ctrl |= CTRL_SET_WORD_LENGTH(0); 70 + ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf); 71 + break; 72 + case DRM_FORMAT_XRGB8888: 73 + dev_dbg(drm->dev, "Setting up XRGB8888 mode\n"); 74 + ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT); 75 + ctrl |= CTRL_SET_WORD_LENGTH(3); 76 + /* Do not use packed pixels = one pixel per word instead. */ 77 + ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7); 78 + break; 79 + default: 80 + dev_err(drm->dev, "Unhandled pixel format %08x\n", format); 81 + return -EINVAL; 82 + } 83 + 84 + writel(ctrl1, mxsfb->base + LCDC_CTRL1); 85 + writel(ctrl, mxsfb->base + LCDC_CTRL); 86 + 87 + return 0; 88 + } 89 + 90 + static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb) 91 + { 92 + u32 reg; 93 + 94 + if (mxsfb->clk_disp_axi) 95 + clk_prepare_enable(mxsfb->clk_disp_axi); 96 + clk_prepare_enable(mxsfb->clk); 97 + mxsfb_enable_axi_clk(mxsfb); 98 + 99 + /* If it was disabled, re-enable the mode again */ 100 + writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET); 101 + 102 + /* Enable the SYNC signals first, then the DMA engine */ 103 + reg = readl(mxsfb->base + LCDC_VDCTRL4); 104 + reg |= VDCTRL4_SYNC_SIGNALS_ON; 105 + writel(reg, mxsfb->base + LCDC_VDCTRL4); 106 + 107 + writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET); 108 + } 109 + 110 + static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb) 111 + { 112 + u32 reg; 113 + 114 + /* 115 + * Even if we disable the controller here, it will still continue 116 + * until its FIFOs are running out of data 117 + */ 118 + writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_CLR); 119 + 120 + readl_poll_timeout(mxsfb->base + LCDC_CTRL, reg, !(reg & CTRL_RUN), 121 + 0, 1000); 122 + 123 + reg = readl(mxsfb->base + LCDC_VDCTRL4); 124 + reg &= ~VDCTRL4_SYNC_SIGNALS_ON; 125 + writel(reg, mxsfb->base + LCDC_VDCTRL4); 126 + 127 + mxsfb_disable_axi_clk(mxsfb); 128 + 129 + clk_disable_unprepare(mxsfb->clk); 130 + if (mxsfb->clk_disp_axi) 131 + clk_disable_unprepare(mxsfb->clk_disp_axi); 132 + } 133 + 134 + static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) 135 + { 136 + struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode; 137 + const u32 bus_flags = mxsfb->connector.display_info.bus_flags; 138 + u32 vdctrl0, vsync_pulse_len, hsync_pulse_len; 139 + int err; 140 + 141 + /* 142 + * It seems, you can't re-program the controller if it is still 143 + * running. This may lead to shifted pictures (FIFO issue?), so 144 + * first stop the controller and drain its FIFOs. 145 + */ 146 + mxsfb_enable_axi_clk(mxsfb); 147 + 148 + /* Clear the FIFOs */ 149 + writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET); 150 + 151 + err = mxsfb_set_pixel_fmt(mxsfb); 152 + if (err) 153 + return; 154 + 155 + clk_set_rate(mxsfb->clk, m->crtc_clock * 1000); 156 + 157 + writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) | 158 + TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay), 159 + mxsfb->base + mxsfb->devdata->transfer_count); 160 + 161 + vsync_pulse_len = m->crtc_vsync_end - m->crtc_vsync_start; 162 + 163 + vdctrl0 = VDCTRL0_ENABLE_PRESENT | /* Always in DOTCLOCK mode */ 164 + VDCTRL0_VSYNC_PERIOD_UNIT | 165 + VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | 166 + VDCTRL0_SET_VSYNC_PULSE_WIDTH(vsync_pulse_len); 167 + if (m->flags & DRM_MODE_FLAG_PHSYNC) 168 + vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH; 169 + if (m->flags & DRM_MODE_FLAG_PVSYNC) 170 + vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH; 171 + if (bus_flags & DRM_BUS_FLAG_DE_HIGH) 172 + vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH; 173 + if (bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE) 174 + vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING; 175 + 176 + writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0); 177 + 178 + /* Frame length in lines. */ 179 + writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1); 180 + 181 + /* Line length in units of clocks or pixels. */ 182 + hsync_pulse_len = m->crtc_hsync_end - m->crtc_hsync_start; 183 + writel(set_hsync_pulse_width(mxsfb, hsync_pulse_len) | 184 + VDCTRL2_SET_HSYNC_PERIOD(m->crtc_htotal), 185 + mxsfb->base + LCDC_VDCTRL2); 186 + 187 + writel(SET_HOR_WAIT_CNT(m->crtc_hblank_end - m->crtc_hsync_end) | 188 + SET_VERT_WAIT_CNT(m->crtc_vblank_end - m->crtc_vsync_end), 189 + mxsfb->base + LCDC_VDCTRL3); 190 + 191 + writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay), 192 + mxsfb->base + LCDC_VDCTRL4); 193 + 194 + mxsfb_disable_axi_clk(mxsfb); 195 + } 196 + 197 + void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb) 198 + { 199 + mxsfb_crtc_mode_set_nofb(mxsfb); 200 + mxsfb_enable_controller(mxsfb); 201 + } 202 + 203 + void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb) 204 + { 205 + mxsfb_disable_controller(mxsfb); 206 + } 207 + 208 + void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, 209 + struct drm_plane_state *state) 210 + { 211 + struct drm_simple_display_pipe *pipe = &mxsfb->pipe; 212 + struct drm_crtc *crtc = &pipe->crtc; 213 + struct drm_framebuffer *fb = pipe->plane.state->fb; 214 + struct drm_pending_vblank_event *event; 215 + struct drm_gem_cma_object *gem; 216 + 217 + if (!crtc) 218 + return; 219 + 220 + spin_lock_irq(&crtc->dev->event_lock); 221 + event = crtc->state->event; 222 + if (event) { 223 + crtc->state->event = NULL; 224 + 225 + if (drm_crtc_vblank_get(crtc) == 0) { 226 + drm_crtc_arm_vblank_event(crtc, event); 227 + } else { 228 + drm_crtc_send_vblank_event(crtc, event); 229 + } 230 + } 231 + spin_unlock_irq(&crtc->dev->event_lock); 232 + 233 + if (!fb) 234 + return; 235 + 236 + gem = drm_fb_cma_get_gem_obj(fb, 0); 237 + 238 + mxsfb_enable_axi_clk(mxsfb); 239 + writel(gem->paddr, mxsfb->base + mxsfb->devdata->next_buf); 240 + mxsfb_disable_axi_clk(mxsfb); 241 + }
+444
drivers/gpu/drm/mxsfb/mxsfb_drv.c
··· 1 + /* 2 + * Copyright (C) 2016 Marek Vasut <marex@denx.de> 3 + * 4 + * This code is based on drivers/video/fbdev/mxsfb.c : 5 + * Copyright (C) 2010 Juergen Beisert, Pengutronix 6 + * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. 7 + * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License 11 + * as published by the Free Software Foundation; either version 2 12 + * of the License, or (at your option) any later version. 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + */ 18 + 19 + #include <linux/module.h> 20 + #include <linux/spinlock.h> 21 + #include <linux/clk.h> 22 + #include <linux/component.h> 23 + #include <linux/list.h> 24 + #include <linux/of_device.h> 25 + #include <linux/of_graph.h> 26 + #include <linux/of_reserved_mem.h> 27 + #include <linux/pm_runtime.h> 28 + #include <linux/reservation.h> 29 + 30 + #include <drm/drmP.h> 31 + #include <drm/drm_atomic.h> 32 + #include <drm/drm_atomic_helper.h> 33 + #include <drm/drm_crtc.h> 34 + #include <drm/drm_crtc_helper.h> 35 + #include <drm/drm_fb_helper.h> 36 + #include <drm/drm_fb_cma_helper.h> 37 + #include <drm/drm_gem_cma_helper.h> 38 + #include <drm/drm_of.h> 39 + #include <drm/drm_panel.h> 40 + #include <drm/drm_simple_kms_helper.h> 41 + 42 + #include "mxsfb_drv.h" 43 + #include "mxsfb_regs.h" 44 + 45 + enum mxsfb_devtype { 46 + MXSFB_V3, 47 + MXSFB_V4, 48 + }; 49 + 50 + static const struct mxsfb_devdata mxsfb_devdata[] = { 51 + [MXSFB_V3] = { 52 + .transfer_count = LCDC_V3_TRANSFER_COUNT, 53 + .cur_buf = LCDC_V3_CUR_BUF, 54 + .next_buf = LCDC_V3_NEXT_BUF, 55 + .debug0 = LCDC_V3_DEBUG0, 56 + .hs_wdth_mask = 0xff, 57 + .hs_wdth_shift = 24, 58 + .ipversion = 3, 59 + }, 60 + [MXSFB_V4] = { 61 + .transfer_count = LCDC_V4_TRANSFER_COUNT, 62 + .cur_buf = LCDC_V4_CUR_BUF, 63 + .next_buf = LCDC_V4_NEXT_BUF, 64 + .debug0 = LCDC_V4_DEBUG0, 65 + .hs_wdth_mask = 0x3fff, 66 + .hs_wdth_shift = 18, 67 + .ipversion = 4, 68 + }, 69 + }; 70 + 71 + static const uint32_t mxsfb_formats[] = { 72 + DRM_FORMAT_XRGB8888, 73 + DRM_FORMAT_RGB565 74 + }; 75 + 76 + static struct mxsfb_drm_private * 77 + drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe *pipe) 78 + { 79 + return container_of(pipe, struct mxsfb_drm_private, pipe); 80 + } 81 + 82 + void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb) 83 + { 84 + if (mxsfb->clk_axi) 85 + clk_prepare_enable(mxsfb->clk_axi); 86 + } 87 + 88 + void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb) 89 + { 90 + if (mxsfb->clk_axi) 91 + clk_disable_unprepare(mxsfb->clk_axi); 92 + } 93 + 94 + static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = { 95 + .fb_create = drm_fb_cma_create, 96 + .atomic_check = drm_atomic_helper_check, 97 + .atomic_commit = drm_atomic_helper_commit, 98 + }; 99 + 100 + static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe, 101 + struct drm_crtc_state *crtc_state) 102 + { 103 + struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); 104 + 105 + mxsfb_crtc_enable(mxsfb); 106 + } 107 + 108 + static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe) 109 + { 110 + struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); 111 + 112 + mxsfb_crtc_disable(mxsfb); 113 + } 114 + 115 + static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe, 116 + struct drm_plane_state *plane_state) 117 + { 118 + struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); 119 + 120 + mxsfb_plane_atomic_update(mxsfb, plane_state); 121 + } 122 + 123 + static int mxsfb_pipe_prepare_fb(struct drm_simple_display_pipe *pipe, 124 + struct drm_plane_state *plane_state) 125 + { 126 + return drm_fb_cma_prepare_fb(&pipe->plane, plane_state); 127 + } 128 + 129 + struct drm_simple_display_pipe_funcs mxsfb_funcs = { 130 + .enable = mxsfb_pipe_enable, 131 + .disable = mxsfb_pipe_disable, 132 + .update = mxsfb_pipe_update, 133 + .prepare_fb = mxsfb_pipe_prepare_fb, 134 + }; 135 + 136 + static int mxsfb_load(struct drm_device *drm, unsigned long flags) 137 + { 138 + struct platform_device *pdev = to_platform_device(drm->dev); 139 + struct mxsfb_drm_private *mxsfb; 140 + struct resource *res; 141 + int ret; 142 + 143 + mxsfb = devm_kzalloc(&pdev->dev, sizeof(*mxsfb), GFP_KERNEL); 144 + if (!mxsfb) 145 + return -ENOMEM; 146 + 147 + drm->dev_private = mxsfb; 148 + mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data]; 149 + 150 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 151 + mxsfb->base = devm_ioremap_resource(drm->dev, res); 152 + if (IS_ERR(mxsfb->base)) 153 + return PTR_ERR(mxsfb->base); 154 + 155 + mxsfb->clk = devm_clk_get(drm->dev, NULL); 156 + if (IS_ERR(mxsfb->clk)) 157 + return PTR_ERR(mxsfb->clk); 158 + 159 + mxsfb->clk_axi = devm_clk_get(drm->dev, "axi"); 160 + if (IS_ERR(mxsfb->clk_axi)) 161 + mxsfb->clk_axi = NULL; 162 + 163 + mxsfb->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi"); 164 + if (IS_ERR(mxsfb->clk_disp_axi)) 165 + mxsfb->clk_disp_axi = NULL; 166 + 167 + ret = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32)); 168 + if (ret) 169 + return ret; 170 + 171 + pm_runtime_enable(drm->dev); 172 + 173 + ret = drm_vblank_init(drm, drm->mode_config.num_crtc); 174 + if (ret < 0) { 175 + dev_err(drm->dev, "Failed to initialise vblank\n"); 176 + goto err_vblank; 177 + } 178 + 179 + /* Modeset init */ 180 + drm_mode_config_init(drm); 181 + 182 + ret = mxsfb_create_output(drm); 183 + if (ret < 0) { 184 + dev_err(drm->dev, "Failed to create outputs\n"); 185 + goto err_vblank; 186 + } 187 + 188 + ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs, 189 + mxsfb_formats, ARRAY_SIZE(mxsfb_formats), 190 + &mxsfb->connector); 191 + if (ret < 0) { 192 + dev_err(drm->dev, "Cannot setup simple display pipe\n"); 193 + goto err_vblank; 194 + } 195 + 196 + ret = drm_panel_attach(mxsfb->panel, &mxsfb->connector); 197 + if (ret) { 198 + dev_err(drm->dev, "Cannot connect panel\n"); 199 + goto err_vblank; 200 + } 201 + 202 + drm->mode_config.min_width = MXSFB_MIN_XRES; 203 + drm->mode_config.min_height = MXSFB_MIN_YRES; 204 + drm->mode_config.max_width = MXSFB_MAX_XRES; 205 + drm->mode_config.max_height = MXSFB_MAX_YRES; 206 + drm->mode_config.funcs = &mxsfb_mode_config_funcs; 207 + 208 + drm_mode_config_reset(drm); 209 + 210 + pm_runtime_get_sync(drm->dev); 211 + ret = drm_irq_install(drm, platform_get_irq(pdev, 0)); 212 + pm_runtime_put_sync(drm->dev); 213 + 214 + if (ret < 0) { 215 + dev_err(drm->dev, "Failed to install IRQ handler\n"); 216 + goto err_irq; 217 + } 218 + 219 + drm_kms_helper_poll_init(drm); 220 + 221 + mxsfb->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, 222 + drm->mode_config.num_connector); 223 + if (IS_ERR(mxsfb->fbdev)) { 224 + mxsfb->fbdev = NULL; 225 + dev_err(drm->dev, "Failed to init FB CMA area\n"); 226 + goto err_cma; 227 + } 228 + 229 + platform_set_drvdata(pdev, drm); 230 + 231 + drm_helper_hpd_irq_event(drm); 232 + 233 + return 0; 234 + 235 + err_cma: 236 + drm_irq_uninstall(drm); 237 + err_irq: 238 + drm_panel_detach(mxsfb->panel); 239 + err_vblank: 240 + pm_runtime_disable(drm->dev); 241 + 242 + return ret; 243 + } 244 + 245 + static void mxsfb_unload(struct drm_device *drm) 246 + { 247 + struct mxsfb_drm_private *mxsfb = drm->dev_private; 248 + 249 + if (mxsfb->fbdev) 250 + drm_fbdev_cma_fini(mxsfb->fbdev); 251 + 252 + drm_kms_helper_poll_fini(drm); 253 + drm_mode_config_cleanup(drm); 254 + drm_vblank_cleanup(drm); 255 + 256 + pm_runtime_get_sync(drm->dev); 257 + drm_irq_uninstall(drm); 258 + pm_runtime_put_sync(drm->dev); 259 + 260 + drm->dev_private = NULL; 261 + 262 + pm_runtime_disable(drm->dev); 263 + } 264 + 265 + static void mxsfb_lastclose(struct drm_device *drm) 266 + { 267 + struct mxsfb_drm_private *mxsfb = drm->dev_private; 268 + 269 + drm_fbdev_cma_restore_mode(mxsfb->fbdev); 270 + } 271 + 272 + static int mxsfb_enable_vblank(struct drm_device *drm, unsigned int crtc) 273 + { 274 + struct mxsfb_drm_private *mxsfb = drm->dev_private; 275 + 276 + /* Clear and enable VBLANK IRQ */ 277 + mxsfb_enable_axi_clk(mxsfb); 278 + writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); 279 + writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET); 280 + mxsfb_disable_axi_clk(mxsfb); 281 + 282 + return 0; 283 + } 284 + 285 + static void mxsfb_disable_vblank(struct drm_device *drm, unsigned int crtc) 286 + { 287 + struct mxsfb_drm_private *mxsfb = drm->dev_private; 288 + 289 + /* Disable and clear VBLANK IRQ */ 290 + mxsfb_enable_axi_clk(mxsfb); 291 + writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR); 292 + writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); 293 + mxsfb_disable_axi_clk(mxsfb); 294 + } 295 + 296 + static void mxsfb_irq_preinstall(struct drm_device *drm) 297 + { 298 + mxsfb_disable_vblank(drm, 0); 299 + } 300 + 301 + static irqreturn_t mxsfb_irq_handler(int irq, void *data) 302 + { 303 + struct drm_device *drm = data; 304 + struct mxsfb_drm_private *mxsfb = drm->dev_private; 305 + u32 reg; 306 + 307 + mxsfb_enable_axi_clk(mxsfb); 308 + 309 + reg = readl(mxsfb->base + LCDC_CTRL1); 310 + 311 + if (reg & CTRL1_CUR_FRAME_DONE_IRQ) 312 + drm_crtc_handle_vblank(&mxsfb->pipe.crtc); 313 + 314 + writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); 315 + 316 + mxsfb_disable_axi_clk(mxsfb); 317 + 318 + return IRQ_HANDLED; 319 + } 320 + 321 + static const struct file_operations fops = { 322 + .owner = THIS_MODULE, 323 + .open = drm_open, 324 + .release = drm_release, 325 + .unlocked_ioctl = drm_ioctl, 326 + #ifdef CONFIG_COMPAT 327 + .compat_ioctl = drm_compat_ioctl, 328 + #endif 329 + .poll = drm_poll, 330 + .read = drm_read, 331 + .llseek = noop_llseek, 332 + .mmap = drm_gem_cma_mmap, 333 + }; 334 + 335 + static struct drm_driver mxsfb_driver = { 336 + .driver_features = DRIVER_GEM | DRIVER_MODESET | 337 + DRIVER_PRIME | DRIVER_ATOMIC | 338 + DRIVER_HAVE_IRQ, 339 + .lastclose = mxsfb_lastclose, 340 + .irq_handler = mxsfb_irq_handler, 341 + .irq_preinstall = mxsfb_irq_preinstall, 342 + .irq_uninstall = mxsfb_irq_preinstall, 343 + .get_vblank_counter = drm_vblank_no_hw_counter, 344 + .enable_vblank = mxsfb_enable_vblank, 345 + .disable_vblank = mxsfb_disable_vblank, 346 + .gem_free_object = drm_gem_cma_free_object, 347 + .gem_vm_ops = &drm_gem_cma_vm_ops, 348 + .dumb_create = drm_gem_cma_dumb_create, 349 + .dumb_map_offset = drm_gem_cma_dumb_map_offset, 350 + .dumb_destroy = drm_gem_dumb_destroy, 351 + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 352 + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 353 + .gem_prime_export = drm_gem_prime_export, 354 + .gem_prime_import = drm_gem_prime_import, 355 + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, 356 + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, 357 + .gem_prime_vmap = drm_gem_cma_prime_vmap, 358 + .gem_prime_vunmap = drm_gem_cma_prime_vunmap, 359 + .gem_prime_mmap = drm_gem_cma_prime_mmap, 360 + .fops = &fops, 361 + .name = "mxsfb-drm", 362 + .desc = "MXSFB Controller DRM", 363 + .date = "20160824", 364 + .major = 1, 365 + .minor = 0, 366 + }; 367 + 368 + static const struct platform_device_id mxsfb_devtype[] = { 369 + { .name = "imx23-fb", .driver_data = MXSFB_V3, }, 370 + { .name = "imx28-fb", .driver_data = MXSFB_V4, }, 371 + { .name = "imx6sx-fb", .driver_data = MXSFB_V4, }, 372 + { /* sentinel */ } 373 + }; 374 + MODULE_DEVICE_TABLE(platform, mxsfb_devtype); 375 + 376 + static const struct of_device_id mxsfb_dt_ids[] = { 377 + { .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], }, 378 + { .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], }, 379 + { .compatible = "fsl,imx6sx-lcdif", .data = &mxsfb_devtype[2], }, 380 + { /* sentinel */ } 381 + }; 382 + MODULE_DEVICE_TABLE(of, mxsfb_dt_ids); 383 + 384 + static int mxsfb_probe(struct platform_device *pdev) 385 + { 386 + struct drm_device *drm; 387 + const struct of_device_id *of_id = 388 + of_match_device(mxsfb_dt_ids, &pdev->dev); 389 + int ret; 390 + 391 + if (!pdev->dev.of_node) 392 + return -ENODEV; 393 + 394 + if (of_id) 395 + pdev->id_entry = of_id->data; 396 + 397 + drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev); 398 + if (!drm) 399 + return -ENOMEM; 400 + 401 + ret = mxsfb_load(drm, 0); 402 + if (ret) 403 + goto err_free; 404 + 405 + ret = drm_dev_register(drm, 0); 406 + if (ret) 407 + goto err_unload; 408 + 409 + return 0; 410 + 411 + err_unload: 412 + mxsfb_unload(drm); 413 + err_free: 414 + drm_dev_unref(drm); 415 + 416 + return ret; 417 + } 418 + 419 + static int mxsfb_remove(struct platform_device *pdev) 420 + { 421 + struct drm_device *drm = platform_get_drvdata(pdev); 422 + 423 + drm_dev_unregister(drm); 424 + mxsfb_unload(drm); 425 + drm_dev_unref(drm); 426 + 427 + return 0; 428 + } 429 + 430 + static struct platform_driver mxsfb_platform_driver = { 431 + .probe = mxsfb_probe, 432 + .remove = mxsfb_remove, 433 + .id_table = mxsfb_devtype, 434 + .driver = { 435 + .name = "mxsfb", 436 + .of_match_table = mxsfb_dt_ids, 437 + }, 438 + }; 439 + 440 + module_platform_driver(mxsfb_platform_driver); 441 + 442 + MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); 443 + MODULE_DESCRIPTION("Freescale MXS DRM/KMS driver"); 444 + MODULE_LICENSE("GPL");
+54
drivers/gpu/drm/mxsfb/mxsfb_drv.h
··· 1 + /* 2 + * Copyright (C) 2016 Marek Vasut <marex@denx.de> 3 + * 4 + * i.MX23/i.MX28/i.MX6SX MXSFB LCD controller driver. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 2 9 + * of the License, or (at your option) any later version. 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + */ 15 + 16 + #ifndef __MXSFB_DRV_H__ 17 + #define __MXSFB_DRV_H__ 18 + 19 + struct mxsfb_devdata { 20 + unsigned int transfer_count; 21 + unsigned int cur_buf; 22 + unsigned int next_buf; 23 + unsigned int debug0; 24 + unsigned int hs_wdth_mask; 25 + unsigned int hs_wdth_shift; 26 + unsigned int ipversion; 27 + }; 28 + 29 + struct mxsfb_drm_private { 30 + const struct mxsfb_devdata *devdata; 31 + 32 + void __iomem *base; /* registers */ 33 + struct clk *clk; 34 + struct clk *clk_axi; 35 + struct clk *clk_disp_axi; 36 + 37 + struct drm_simple_display_pipe pipe; 38 + struct drm_connector connector; 39 + struct drm_panel *panel; 40 + struct drm_fbdev_cma *fbdev; 41 + }; 42 + 43 + int mxsfb_setup_crtc(struct drm_device *dev); 44 + int mxsfb_create_output(struct drm_device *dev); 45 + 46 + void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb); 47 + void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb); 48 + 49 + void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb); 50 + void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb); 51 + void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, 52 + struct drm_plane_state *state); 53 + 54 + #endif /* __MXSFB_DRV_H__ */
+131
drivers/gpu/drm/mxsfb/mxsfb_out.c
··· 1 + /* 2 + * Copyright (C) 2016 Marek Vasut <marex@denx.de> 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation; either version 2 7 + * of the License, or (at your option) any later version. 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #include <linux/of_graph.h> 15 + 16 + #include <drm/drm_atomic.h> 17 + #include <drm/drm_atomic_helper.h> 18 + #include <drm/drm_crtc.h> 19 + #include <drm/drm_crtc_helper.h> 20 + #include <drm/drm_fb_cma_helper.h> 21 + #include <drm/drm_gem_cma_helper.h> 22 + #include <drm/drm_panel.h> 23 + #include <drm/drm_plane_helper.h> 24 + #include <drm/drm_simple_kms_helper.h> 25 + #include <drm/drmP.h> 26 + 27 + #include "mxsfb_drv.h" 28 + 29 + static struct mxsfb_drm_private * 30 + drm_connector_to_mxsfb_drm_private(struct drm_connector *connector) 31 + { 32 + return container_of(connector, struct mxsfb_drm_private, connector); 33 + } 34 + 35 + static int mxsfb_panel_get_modes(struct drm_connector *connector) 36 + { 37 + struct mxsfb_drm_private *mxsfb = 38 + drm_connector_to_mxsfb_drm_private(connector); 39 + 40 + if (mxsfb->panel) 41 + return mxsfb->panel->funcs->get_modes(mxsfb->panel); 42 + 43 + return 0; 44 + } 45 + 46 + static const struct 47 + drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = { 48 + .get_modes = mxsfb_panel_get_modes, 49 + }; 50 + 51 + static enum drm_connector_status 52 + mxsfb_panel_connector_detect(struct drm_connector *connector, bool force) 53 + { 54 + struct mxsfb_drm_private *mxsfb = 55 + drm_connector_to_mxsfb_drm_private(connector); 56 + 57 + if (mxsfb->panel) 58 + return connector_status_connected; 59 + 60 + return connector_status_disconnected; 61 + } 62 + 63 + static void mxsfb_panel_connector_destroy(struct drm_connector *connector) 64 + { 65 + struct mxsfb_drm_private *mxsfb = 66 + drm_connector_to_mxsfb_drm_private(connector); 67 + 68 + if (mxsfb->panel) 69 + drm_panel_detach(mxsfb->panel); 70 + 71 + drm_connector_unregister(connector); 72 + drm_connector_cleanup(connector); 73 + } 74 + 75 + static const struct drm_connector_funcs mxsfb_panel_connector_funcs = { 76 + .dpms = drm_atomic_helper_connector_dpms, 77 + .detect = mxsfb_panel_connector_detect, 78 + .fill_modes = drm_helper_probe_single_connector_modes, 79 + .destroy = mxsfb_panel_connector_destroy, 80 + .reset = drm_atomic_helper_connector_reset, 81 + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 82 + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 83 + }; 84 + 85 + static int mxsfb_attach_endpoint(struct drm_device *drm, 86 + const struct of_endpoint *ep) 87 + { 88 + struct mxsfb_drm_private *mxsfb = drm->dev_private; 89 + struct device_node *np; 90 + struct drm_panel *panel; 91 + int ret = -EPROBE_DEFER; 92 + 93 + np = of_graph_get_remote_port_parent(ep->local_node); 94 + panel = of_drm_find_panel(np); 95 + of_node_put(np); 96 + 97 + if (!panel) 98 + return -EPROBE_DEFER; 99 + 100 + mxsfb->connector.dpms = DRM_MODE_DPMS_OFF; 101 + mxsfb->connector.polled = 0; 102 + drm_connector_helper_add(&mxsfb->connector, 103 + &mxsfb_panel_connector_helper_funcs); 104 + ret = drm_connector_init(drm, &mxsfb->connector, 105 + &mxsfb_panel_connector_funcs, 106 + DRM_MODE_CONNECTOR_Unknown); 107 + if (!ret) 108 + mxsfb->panel = panel; 109 + 110 + return ret; 111 + } 112 + 113 + int mxsfb_create_output(struct drm_device *drm) 114 + { 115 + struct device_node *ep_np = NULL; 116 + struct of_endpoint ep; 117 + int ret; 118 + 119 + for_each_endpoint_of_node(drm->dev->of_node, ep_np) { 120 + ret = of_graph_parse_endpoint(ep_np, &ep); 121 + if (!ret) 122 + ret = mxsfb_attach_endpoint(drm, &ep); 123 + 124 + if (ret) { 125 + of_node_put(ep_np); 126 + return ret; 127 + } 128 + } 129 + 130 + return 0; 131 + }
+114
drivers/gpu/drm/mxsfb/mxsfb_regs.h
··· 1 + /* 2 + * Copyright (C) 2010 Juergen Beisert, Pengutronix 3 + * Copyright (C) 2016 Marek Vasut <marex@denx.de> 4 + * 5 + * i.MX23/i.MX28/i.MX6SX MXSFB LCD controller driver. 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License 9 + * as published by the Free Software Foundation; either version 2 10 + * of the License, or (at your option) any later version. 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + */ 16 + 17 + #ifndef __MXSFB_REGS_H__ 18 + #define __MXSFB_REGS_H__ 19 + 20 + #define REG_SET 4 21 + #define REG_CLR 8 22 + 23 + #define LCDC_CTRL 0x00 24 + #define LCDC_CTRL1 0x10 25 + #define LCDC_V3_TRANSFER_COUNT 0x20 26 + #define LCDC_V4_TRANSFER_COUNT 0x30 27 + #define LCDC_V4_CUR_BUF 0x40 28 + #define LCDC_V4_NEXT_BUF 0x50 29 + #define LCDC_V3_CUR_BUF 0x30 30 + #define LCDC_V3_NEXT_BUF 0x40 31 + #define LCDC_VDCTRL0 0x70 32 + #define LCDC_VDCTRL1 0x80 33 + #define LCDC_VDCTRL2 0x90 34 + #define LCDC_VDCTRL3 0xa0 35 + #define LCDC_VDCTRL4 0xb0 36 + #define LCDC_V4_DEBUG0 0x1d0 37 + #define LCDC_V3_DEBUG0 0x1f0 38 + 39 + #define CTRL_SFTRST (1 << 31) 40 + #define CTRL_CLKGATE (1 << 30) 41 + #define CTRL_BYPASS_COUNT (1 << 19) 42 + #define CTRL_VSYNC_MODE (1 << 18) 43 + #define CTRL_DOTCLK_MODE (1 << 17) 44 + #define CTRL_DATA_SELECT (1 << 16) 45 + #define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10) 46 + #define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3) 47 + #define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8) 48 + #define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3) 49 + #define CTRL_MASTER (1 << 5) 50 + #define CTRL_DF16 (1 << 3) 51 + #define CTRL_DF18 (1 << 2) 52 + #define CTRL_DF24 (1 << 1) 53 + #define CTRL_RUN (1 << 0) 54 + 55 + #define CTRL1_FIFO_CLEAR (1 << 21) 56 + #define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16) 57 + #define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf) 58 + #define CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13) 59 + #define CTRL1_CUR_FRAME_DONE_IRQ (1 << 9) 60 + 61 + #define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16) 62 + #define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff) 63 + #define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff) 64 + #define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff) 65 + 66 + #define VDCTRL0_ENABLE_PRESENT (1 << 28) 67 + #define VDCTRL0_VSYNC_ACT_HIGH (1 << 27) 68 + #define VDCTRL0_HSYNC_ACT_HIGH (1 << 26) 69 + #define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25) 70 + #define VDCTRL0_ENABLE_ACT_HIGH (1 << 24) 71 + #define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21) 72 + #define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20) 73 + #define VDCTRL0_HALF_LINE (1 << 19) 74 + #define VDCTRL0_HALF_LINE_MODE (1 << 18) 75 + #define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff) 76 + #define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff) 77 + 78 + #define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff) 79 + #define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff) 80 + 81 + #define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29) 82 + #define VDCTRL3_VSYNC_ONLY (1 << 28) 83 + #define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16) 84 + #define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff) 85 + #define SET_VERT_WAIT_CNT(x) ((x) & 0xffff) 86 + #define GET_VERT_WAIT_CNT(x) ((x) & 0xffff) 87 + 88 + #define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */ 89 + #define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */ 90 + #define VDCTRL4_SYNC_SIGNALS_ON (1 << 18) 91 + #define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff) 92 + 93 + #define DEBUG0_HSYNC (1 < 26) 94 + #define DEBUG0_VSYNC (1 < 25) 95 + 96 + #define MXSFB_MIN_XRES 120 97 + #define MXSFB_MIN_YRES 120 98 + #define MXSFB_MAX_XRES 0xffff 99 + #define MXSFB_MAX_YRES 0xffff 100 + 101 + #define RED 0 102 + #define GREEN 1 103 + #define BLUE 2 104 + #define TRANSP 3 105 + 106 + #define STMLCDIF_8BIT 1 /* pixel data bus to the display is of 8 bit width */ 107 + #define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */ 108 + #define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */ 109 + #define STMLCDIF_24BIT 3 /* pixel data bus to the display is of 24 bit width */ 110 + 111 + #define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT (1 << 6) 112 + #define MXSFB_SYNC_DOTCLK_FALLING_ACT (1 << 7) /* negative edge sampling */ 113 + 114 + #endif /* __MXSFB_REGS_H__ */