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

Merge tag 'imx-drm-next-2015-01-09' of git://git.pengutronix.de/git/pza/linux into drm-next

imx-drm mode fixup support, imx-hdmi bridge conversion and imx-drm cleanup

- Implement mode_fixup for a DI vertical timing limitation
- Use generic DRM OF helpers in DRM core
- Convert imx-hdmi to dw_hdmi drm_bridge and add rockchip
driver
- Add DC use counter to fix multi-display support
- Simplify handling of DI clock flags
- A few small fixes and cleanup

* tag 'imx-drm-next-2015-01-09' of git://git.pengutronix.de/git/pza/linux: (26 commits)
imx-drm: core: handling of DI clock flags to ipu_crtc_mode_set()
gpu: ipu-di: Switch to DIV_ROUND_CLOSEST for DI clock divider calc
gpu: ipu-v3: Use videomode in struct ipu_di_signal_cfg
imx-drm: encoder prepare/mode_set must use adjusted mode
imx-drm: ipuv3-crtc: Implement mode_fixup
drm_modes: add drm_display_mode_to_videomode
gpu: ipu-di: remove some non-functional code
gpu: ipu-di: Add ipu_di_adjust_videomode()
drm: rockchip: export functions needed by rockchip dw_hdmi bridge driver
drm: bridge/dw_hdmi: request interrupt only after initializing the mutes
drm: bridge/dw_hdmi: add rockchip rk3288 support
dt-bindings: Add documentation for rockchip dw hdmi
drm: bridge/dw_hdmi: add function dw_hdmi_phy_enable_spare
drm: bridge/dw_hdmi: clear i2cmphy_stat0 reg in hdmi_phy_wait_i2c_done
drm: bridge/dw_hdmi: add mode_valid support
drm: bridge/dw_hdmi: add support for multi-byte register width access
dt-bindings: add document for dw_hdmi
drm: imx: imx-hdmi: move imx-hdmi to bridge/dw_hdmi
drm: imx: imx-hdmi: split phy configuration to platform driver
drm: imx: imx-hdmi: convert imx-hdmi to drm_bridge mode
...

+1341 -575
+50
Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
··· 1 + DesignWare HDMI bridge bindings 2 + 3 + Required properties: 4 + - compatible: platform specific such as: 5 + * "snps,dw-hdmi-tx" 6 + * "fsl,imx6q-hdmi" 7 + * "fsl,imx6dl-hdmi" 8 + * "rockchip,rk3288-dw-hdmi" 9 + - reg: Physical base address and length of the controller's registers. 10 + - interrupts: The HDMI interrupt number 11 + - clocks, clock-names : must have the phandles to the HDMI iahb and isfr clocks, 12 + as described in Documentation/devicetree/bindings/clock/clock-bindings.txt, 13 + the clocks are soc specific, the clock-names should be "iahb", "isfr" 14 + -port@[X]: SoC specific port nodes with endpoint definitions as defined 15 + in Documentation/devicetree/bindings/media/video-interfaces.txt, 16 + please refer to the SoC specific binding document: 17 + * Documentation/devicetree/bindings/drm/imx/hdmi.txt 18 + * Documentation/devicetree/bindings/video/dw_hdmi-rockchip.txt 19 + 20 + Optional properties 21 + - reg-io-width: the width of the reg:1,4, default set to 1 if not present 22 + - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing 23 + - clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec" 24 + 25 + Example: 26 + hdmi: hdmi@0120000 { 27 + compatible = "fsl,imx6q-hdmi"; 28 + reg = <0x00120000 0x9000>; 29 + interrupts = <0 115 0x04>; 30 + gpr = <&gpr>; 31 + clocks = <&clks 123>, <&clks 124>; 32 + clock-names = "iahb", "isfr"; 33 + ddc-i2c-bus = <&i2c2>; 34 + 35 + port@0 { 36 + reg = <0>; 37 + 38 + hdmi_mux_0: endpoint { 39 + remote-endpoint = <&ipu1_di0_hdmi>; 40 + }; 41 + }; 42 + 43 + port@1 { 44 + reg = <1>; 45 + 46 + hdmi_mux_1: endpoint { 47 + remote-endpoint = <&ipu1_di1_hdmi>; 48 + }; 49 + }; 50 + };
+46
Documentation/devicetree/bindings/video/dw_hdmi-rockchip.txt
··· 1 + Rockchip specific extensions to the Synopsys Designware HDMI 2 + ================================ 3 + 4 + Required properties: 5 + - compatible: "rockchip,rk3288-dw-hdmi"; 6 + - reg: Physical base address and length of the controller's registers. 7 + - clocks: phandle to hdmi iahb and isfr clocks. 8 + - clock-names: should be "iahb" "isfr" 9 + - rockchip,grf: this soc should set GRF regs to mux vopl/vopb. 10 + - interrupts: HDMI interrupt number 11 + - ports: contain a port node with endpoint definitions as defined in 12 + Documentation/devicetree/bindings/media/video-interfaces.txt. For 13 + vopb,set the reg = <0> and set the reg = <1> for vopl. 14 + - reg-io-width: the width of the reg:1,4, the value should be 4 on 15 + rk3288 platform 16 + 17 + Optional properties 18 + - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing 19 + - clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec" 20 + 21 + Example: 22 + hdmi: hdmi@ff980000 { 23 + compatible = "rockchip,rk3288-dw-hdmi"; 24 + reg = <0xff980000 0x20000>; 25 + reg-io-width = <4>; 26 + ddc-i2c-bus = <&i2c5>; 27 + rockchip,grf = <&grf>; 28 + interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; 29 + clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>; 30 + clock-names = "iahb", "isfr"; 31 + status = "disabled"; 32 + ports { 33 + hdmi_in: port { 34 + #address-cells = <1>; 35 + #size-cells = <0>; 36 + hdmi_in_vopb: endpoint@0 { 37 + reg = <0>; 38 + remote-endpoint = <&vopb_out_hdmi>; 39 + }; 40 + hdmi_in_vopl: endpoint@1 { 41 + reg = <1>; 42 + remote-endpoint = <&vopl_out_hdmi>; 43 + }; 44 + }; 45 + }; 46 + };
+5
drivers/gpu/drm/bridge/Kconfig
··· 3 3 depends on DRM 4 4 select DRM_KMS_HELPER 5 5 ---help--- 6 + 7 + config DRM_DW_HDMI 8 + tristate 9 + depends on DRM 10 + select DRM_KMS_HELPER
+1
drivers/gpu/drm/bridge/Makefile
··· 1 1 ccflags-y := -Iinclude/drm 2 2 3 3 obj-$(CONFIG_DRM_PTN3460) += ptn3460.o 4 + obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o
+40
drivers/gpu/drm/drm_modes.c
··· 615 615 } 616 616 EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode); 617 617 618 + /** 619 + * drm_display_mode_to_videomode - fill in @vm using @dmode, 620 + * @dmode: drm_display_mode structure to use as source 621 + * @vm: videomode structure to use as destination 622 + * 623 + * Fills out @vm using the display mode specified in @dmode. 624 + */ 625 + void drm_display_mode_to_videomode(const struct drm_display_mode *dmode, 626 + struct videomode *vm) 627 + { 628 + vm->hactive = dmode->hdisplay; 629 + vm->hfront_porch = dmode->hsync_start - dmode->hdisplay; 630 + vm->hsync_len = dmode->hsync_end - dmode->hsync_start; 631 + vm->hback_porch = dmode->htotal - dmode->hsync_end; 632 + 633 + vm->vactive = dmode->vdisplay; 634 + vm->vfront_porch = dmode->vsync_start - dmode->vdisplay; 635 + vm->vsync_len = dmode->vsync_end - dmode->vsync_start; 636 + vm->vback_porch = dmode->vtotal - dmode->vsync_end; 637 + 638 + vm->pixelclock = dmode->clock * 1000; 639 + 640 + vm->flags = 0; 641 + if (dmode->flags & DRM_MODE_FLAG_PHSYNC) 642 + vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH; 643 + else if (dmode->flags & DRM_MODE_FLAG_NHSYNC) 644 + vm->flags |= DISPLAY_FLAGS_HSYNC_LOW; 645 + if (dmode->flags & DRM_MODE_FLAG_PVSYNC) 646 + vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH; 647 + else if (dmode->flags & DRM_MODE_FLAG_NVSYNC) 648 + vm->flags |= DISPLAY_FLAGS_VSYNC_LOW; 649 + if (dmode->flags & DRM_MODE_FLAG_INTERLACE) 650 + vm->flags |= DISPLAY_FLAGS_INTERLACED; 651 + if (dmode->flags & DRM_MODE_FLAG_DBLSCAN) 652 + vm->flags |= DISPLAY_FLAGS_DOUBLESCAN; 653 + if (dmode->flags & DRM_MODE_FLAG_DBLCLK) 654 + vm->flags |= DISPLAY_FLAGS_DOUBLECLK; 655 + } 656 + EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode); 657 + 618 658 #ifdef CONFIG_OF 619 659 /** 620 660 * of_get_drm_display_mode - get a drm_display_mode from devicetree
+1
drivers/gpu/drm/imx/Kconfig
··· 49 49 50 50 config DRM_IMX_HDMI 51 51 tristate "Freescale i.MX DRM HDMI" 52 + select DRM_DW_HDMI 52 53 depends on DRM_IMX 53 54 help 54 55 Choose this if you want to use HDMI on i.MX6.
+1 -1
drivers/gpu/drm/imx/Makefile
··· 9 9 10 10 imx-ipuv3-crtc-objs := ipuv3-crtc.o ipuv3-plane.o 11 11 obj-$(CONFIG_DRM_IMX_IPUV3) += imx-ipuv3-crtc.o 12 - obj-$(CONFIG_DRM_IMX_HDMI) += imx-hdmi.o 12 + obj-$(CONFIG_DRM_IMX_HDMI) += dw_hdmi-imx.o
+258
drivers/gpu/drm/imx/dw_hdmi-imx.c
··· 1 + /* Copyright (C) 2011-2013 Freescale Semiconductor, Inc. 2 + * 3 + * derived from imx-hdmi.c(renamed to bridge/dw_hdmi.c now) 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + */ 9 + #include <linux/module.h> 10 + #include <linux/platform_device.h> 11 + #include <linux/component.h> 12 + #include <linux/mfd/syscon.h> 13 + #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> 14 + #include <drm/bridge/dw_hdmi.h> 15 + #include <video/imx-ipu-v3.h> 16 + #include <linux/regmap.h> 17 + #include <drm/drm_of.h> 18 + #include <drm/drmP.h> 19 + #include <drm/drm_crtc_helper.h> 20 + #include <drm/drm_edid.h> 21 + #include <drm/drm_encoder_slave.h> 22 + 23 + #include "imx-drm.h" 24 + 25 + struct imx_hdmi { 26 + struct device *dev; 27 + struct drm_encoder encoder; 28 + struct regmap *regmap; 29 + }; 30 + 31 + static const struct dw_hdmi_mpll_config imx_mpll_cfg[] = { 32 + { 33 + 45250000, { 34 + { 0x01e0, 0x0000 }, 35 + { 0x21e1, 0x0000 }, 36 + { 0x41e2, 0x0000 } 37 + }, 38 + }, { 39 + 92500000, { 40 + { 0x0140, 0x0005 }, 41 + { 0x2141, 0x0005 }, 42 + { 0x4142, 0x0005 }, 43 + }, 44 + }, { 45 + 148500000, { 46 + { 0x00a0, 0x000a }, 47 + { 0x20a1, 0x000a }, 48 + { 0x40a2, 0x000a }, 49 + }, 50 + }, { 51 + ~0UL, { 52 + { 0x00a0, 0x000a }, 53 + { 0x2001, 0x000f }, 54 + { 0x4002, 0x000f }, 55 + }, 56 + } 57 + }; 58 + 59 + static const struct dw_hdmi_curr_ctrl imx_cur_ctr[] = { 60 + /* pixelclk bpp8 bpp10 bpp12 */ 61 + { 62 + 54000000, { 0x091c, 0x091c, 0x06dc }, 63 + }, { 64 + 58400000, { 0x091c, 0x06dc, 0x06dc }, 65 + }, { 66 + 72000000, { 0x06dc, 0x06dc, 0x091c }, 67 + }, { 68 + 74250000, { 0x06dc, 0x0b5c, 0x091c }, 69 + }, { 70 + 118800000, { 0x091c, 0x091c, 0x06dc }, 71 + }, { 72 + 216000000, { 0x06dc, 0x0b5c, 0x091c }, 73 + } 74 + }; 75 + 76 + static const struct dw_hdmi_sym_term imx_sym_term[] = { 77 + /*pixelclk symbol term*/ 78 + { 148500000, 0x800d, 0x0005 }, 79 + { ~0UL, 0x0000, 0x0000 } 80 + }; 81 + 82 + static int dw_hdmi_imx_parse_dt(struct imx_hdmi *hdmi) 83 + { 84 + struct device_node *np = hdmi->dev->of_node; 85 + 86 + hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr"); 87 + if (IS_ERR(hdmi->regmap)) { 88 + dev_err(hdmi->dev, "Unable to get gpr\n"); 89 + return PTR_ERR(hdmi->regmap); 90 + } 91 + 92 + return 0; 93 + } 94 + 95 + static void dw_hdmi_imx_encoder_disable(struct drm_encoder *encoder) 96 + { 97 + } 98 + 99 + static bool dw_hdmi_imx_encoder_mode_fixup(struct drm_encoder *encoder, 100 + const struct drm_display_mode *mode, 101 + struct drm_display_mode *adj_mode) 102 + { 103 + return true; 104 + } 105 + 106 + static void dw_hdmi_imx_encoder_mode_set(struct drm_encoder *encoder, 107 + struct drm_display_mode *mode, 108 + struct drm_display_mode *adj_mode) 109 + { 110 + } 111 + 112 + static void dw_hdmi_imx_encoder_commit(struct drm_encoder *encoder) 113 + { 114 + struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); 115 + int mux = imx_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder); 116 + 117 + regmap_update_bits(hdmi->regmap, IOMUXC_GPR3, 118 + IMX6Q_GPR3_HDMI_MUX_CTL_MASK, 119 + mux << IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT); 120 + } 121 + 122 + static void dw_hdmi_imx_encoder_prepare(struct drm_encoder *encoder) 123 + { 124 + imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24); 125 + } 126 + 127 + static struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = { 128 + .mode_fixup = dw_hdmi_imx_encoder_mode_fixup, 129 + .mode_set = dw_hdmi_imx_encoder_mode_set, 130 + .prepare = dw_hdmi_imx_encoder_prepare, 131 + .commit = dw_hdmi_imx_encoder_commit, 132 + .disable = dw_hdmi_imx_encoder_disable, 133 + }; 134 + 135 + static struct drm_encoder_funcs dw_hdmi_imx_encoder_funcs = { 136 + .destroy = drm_encoder_cleanup, 137 + }; 138 + 139 + static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = { 140 + .mpll_cfg = imx_mpll_cfg, 141 + .cur_ctr = imx_cur_ctr, 142 + .sym_term = imx_sym_term, 143 + .dev_type = IMX6Q_HDMI, 144 + }; 145 + 146 + static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = { 147 + .mpll_cfg = imx_mpll_cfg, 148 + .cur_ctr = imx_cur_ctr, 149 + .sym_term = imx_sym_term, 150 + .dev_type = IMX6DL_HDMI, 151 + }; 152 + 153 + static const struct of_device_id dw_hdmi_imx_dt_ids[] = { 154 + { .compatible = "fsl,imx6q-hdmi", 155 + .data = &imx6q_hdmi_drv_data 156 + }, { 157 + .compatible = "fsl,imx6dl-hdmi", 158 + .data = &imx6dl_hdmi_drv_data 159 + }, 160 + {}, 161 + }; 162 + MODULE_DEVICE_TABLE(of, dw_hdmi_imx_dt_ids); 163 + 164 + static int dw_hdmi_imx_bind(struct device *dev, struct device *master, 165 + void *data) 166 + { 167 + struct platform_device *pdev = to_platform_device(dev); 168 + const struct dw_hdmi_plat_data *plat_data; 169 + const struct of_device_id *match; 170 + struct drm_device *drm = data; 171 + struct drm_encoder *encoder; 172 + struct imx_hdmi *hdmi; 173 + struct resource *iores; 174 + int irq; 175 + int ret; 176 + 177 + if (!pdev->dev.of_node) 178 + return -ENODEV; 179 + 180 + hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); 181 + if (!hdmi) 182 + return -ENOMEM; 183 + 184 + match = of_match_node(dw_hdmi_imx_dt_ids, pdev->dev.of_node); 185 + plat_data = match->data; 186 + hdmi->dev = &pdev->dev; 187 + encoder = &hdmi->encoder; 188 + 189 + irq = platform_get_irq(pdev, 0); 190 + if (irq < 0) 191 + return irq; 192 + 193 + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 194 + if (!iores) 195 + return -ENXIO; 196 + 197 + platform_set_drvdata(pdev, hdmi); 198 + 199 + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); 200 + /* 201 + * If we failed to find the CRTC(s) which this encoder is 202 + * supposed to be connected to, it's because the CRTC has 203 + * not been registered yet. Defer probing, and hope that 204 + * the required CRTC is added later. 205 + */ 206 + if (encoder->possible_crtcs == 0) 207 + return -EPROBE_DEFER; 208 + 209 + ret = dw_hdmi_imx_parse_dt(hdmi); 210 + if (ret < 0) 211 + return ret; 212 + 213 + drm_encoder_helper_add(encoder, &dw_hdmi_imx_encoder_helper_funcs); 214 + drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs, 215 + DRM_MODE_ENCODER_TMDS); 216 + 217 + return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data); 218 + } 219 + 220 + static void dw_hdmi_imx_unbind(struct device *dev, struct device *master, 221 + void *data) 222 + { 223 + return dw_hdmi_unbind(dev, master, data); 224 + } 225 + 226 + static const struct component_ops dw_hdmi_imx_ops = { 227 + .bind = dw_hdmi_imx_bind, 228 + .unbind = dw_hdmi_imx_unbind, 229 + }; 230 + 231 + static int dw_hdmi_imx_probe(struct platform_device *pdev) 232 + { 233 + return component_add(&pdev->dev, &dw_hdmi_imx_ops); 234 + } 235 + 236 + static int dw_hdmi_imx_remove(struct platform_device *pdev) 237 + { 238 + component_del(&pdev->dev, &dw_hdmi_imx_ops); 239 + 240 + return 0; 241 + } 242 + 243 + static struct platform_driver dw_hdmi_imx_platform_driver = { 244 + .probe = dw_hdmi_imx_probe, 245 + .remove = dw_hdmi_imx_remove, 246 + .driver = { 247 + .name = "dwhdmi-imx", 248 + .of_match_table = dw_hdmi_imx_dt_ids, 249 + }, 250 + }; 251 + 252 + module_platform_driver(dw_hdmi_imx_platform_driver); 253 + 254 + MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>"); 255 + MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); 256 + MODULE_DESCRIPTION("IMX6 Specific DW-HDMI Driver Extension"); 257 + MODULE_LICENSE("GPL"); 258 + MODULE_ALIAS("platform:dwhdmi-imx");
+23 -70
drivers/gpu/drm/imx/imx-drm-core.c
··· 25 25 #include <drm/drm_gem_cma_helper.h> 26 26 #include <drm/drm_fb_cma_helper.h> 27 27 #include <drm/drm_plane_helper.h> 28 + #include <drm/drm_of.h> 28 29 29 30 #include "imx-drm.h" 30 31 ··· 47 46 struct drm_crtc *crtc; 48 47 int pipe; 49 48 struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; 50 - struct device_node *port; 51 49 }; 52 50 53 51 static int legacyfb_depth = 16; ··· 116 116 helper = &imx_crtc->imx_drm_helper_funcs; 117 117 if (helper->set_interface_pix_fmt) 118 118 return helper->set_interface_pix_fmt(encoder->crtc, 119 - encoder->encoder_type, interface_pix_fmt, 120 - hsync_pin, vsync_pin); 119 + interface_pix_fmt, hsync_pin, vsync_pin); 121 120 return 0; 122 121 } 123 122 EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins); ··· 364 365 365 366 imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; 366 367 imx_drm_crtc->pipe = imxdrm->pipes++; 367 - imx_drm_crtc->port = port; 368 368 imx_drm_crtc->crtc = crtc; 369 + 370 + crtc->port = port; 369 371 370 372 imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc; 371 373 ··· 408 408 } 409 409 EXPORT_SYMBOL_GPL(imx_drm_remove_crtc); 410 410 411 - /* 412 - * Find the DRM CRTC possible mask for the connected endpoint. 413 - * 414 - * The encoder possible masks are defined by their position in the 415 - * mode_config crtc_list. This means that CRTCs must not be added 416 - * or removed once the DRM device has been fully initialised. 417 - */ 418 - static uint32_t imx_drm_find_crtc_mask(struct imx_drm_device *imxdrm, 419 - struct device_node *endpoint) 420 - { 421 - struct device_node *port; 422 - unsigned i; 423 - 424 - port = of_graph_get_remote_port(endpoint); 425 - if (!port) 426 - return 0; 427 - of_node_put(port); 428 - 429 - for (i = 0; i < MAX_CRTC; i++) { 430 - struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[i]; 431 - 432 - if (imx_drm_crtc && imx_drm_crtc->port == port) 433 - return drm_crtc_mask(imx_drm_crtc->crtc); 434 - } 435 - 436 - return 0; 437 - } 438 - 439 - static struct device_node *imx_drm_of_get_next_endpoint( 440 - const struct device_node *parent, struct device_node *prev) 441 - { 442 - struct device_node *node = of_graph_get_next_endpoint(parent, prev); 443 - 444 - of_node_put(prev); 445 - return node; 446 - } 447 - 448 411 int imx_drm_encoder_parse_of(struct drm_device *drm, 449 412 struct drm_encoder *encoder, struct device_node *np) 450 413 { 451 - struct imx_drm_device *imxdrm = drm->dev_private; 452 - struct device_node *ep = NULL; 453 - uint32_t crtc_mask = 0; 454 - int i; 414 + uint32_t crtc_mask = drm_of_find_possible_crtcs(drm, np); 455 415 456 - for (i = 0; ; i++) { 457 - u32 mask; 458 - 459 - ep = imx_drm_of_get_next_endpoint(np, ep); 460 - if (!ep) 461 - break; 462 - 463 - mask = imx_drm_find_crtc_mask(imxdrm, ep); 464 - 465 - /* 466 - * If we failed to find the CRTC(s) which this encoder is 467 - * supposed to be connected to, it's because the CRTC has 468 - * not been registered yet. Defer probing, and hope that 469 - * the required CRTC is added later. 470 - */ 471 - if (mask == 0) 472 - return -EPROBE_DEFER; 473 - 474 - crtc_mask |= mask; 475 - } 476 - 477 - of_node_put(ep); 478 - if (i == 0) 479 - return -ENOENT; 416 + /* 417 + * If we failed to find the CRTC(s) which this encoder is 418 + * supposed to be connected to, it's because the CRTC has 419 + * not been registered yet. Defer probing, and hope that 420 + * the required CRTC is added later. 421 + */ 422 + if (crtc_mask == 0) 423 + return -EPROBE_DEFER; 480 424 481 425 encoder->possible_crtcs = crtc_mask; 482 426 ··· 430 486 return 0; 431 487 } 432 488 EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of); 489 + 490 + static struct device_node *imx_drm_of_get_next_endpoint( 491 + const struct device_node *parent, struct device_node *prev) 492 + { 493 + struct device_node *node = of_graph_get_next_endpoint(parent, prev); 494 + 495 + of_node_put(prev); 496 + return node; 497 + } 433 498 434 499 /* 435 500 * @node: device tree node containing encoder input ports ··· 463 510 464 511 port = of_graph_get_remote_port(ep); 465 512 of_node_put(port); 466 - if (port == imx_crtc->port) { 513 + if (port == imx_crtc->crtc->port) { 467 514 ret = of_graph_parse_endpoint(ep, &endpoint); 468 515 return ret ? ret : endpoint.port; 469 516 }
+1 -1
drivers/gpu/drm/imx/imx-drm.h
··· 17 17 struct imx_drm_crtc_helper_funcs { 18 18 int (*enable_vblank)(struct drm_crtc *crtc); 19 19 void (*disable_vblank)(struct drm_crtc *crtc); 20 - int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type, 20 + int (*set_interface_pix_fmt)(struct drm_crtc *crtc, 21 21 u32 pix_fmt, int hsync_pin, int vsync_pin); 22 22 const struct drm_crtc_helper_funcs *crtc_helper_funcs; 23 23 const struct drm_crtc_funcs *crtc_funcs;
+340 -392
drivers/gpu/drm/imx/imx-hdmi.c drivers/gpu/drm/bridge/dw_hdmi.c
··· 6 6 * the Free Software Foundation; either version 2 of the License, or 7 7 * (at your option) any later version. 8 8 * 9 - * SH-Mobile High-Definition Multimedia Interface (HDMI) driver 10 - * for SLISHDMI13T and SLIPHDMIT IP cores 9 + * Designware High-Definition Multimedia Interface (HDMI) driver 11 10 * 12 11 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> 13 12 */ 14 - 15 - #include <linux/component.h> 13 + #include <linux/module.h> 16 14 #include <linux/irq.h> 17 15 #include <linux/delay.h> 18 16 #include <linux/err.h> 19 17 #include <linux/clk.h> 20 18 #include <linux/hdmi.h> 21 - #include <linux/regmap.h> 22 - #include <linux/mfd/syscon.h> 23 - #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> 24 19 #include <linux/of_device.h> 25 20 21 + #include <drm/drm_of.h> 26 22 #include <drm/drmP.h> 27 23 #include <drm/drm_crtc_helper.h> 28 24 #include <drm/drm_edid.h> 29 25 #include <drm/drm_encoder_slave.h> 30 - #include <video/imx-ipu-v3.h> 26 + #include <drm/bridge/dw_hdmi.h> 31 27 32 - #include "imx-hdmi.h" 33 - #include "imx-drm.h" 28 + #include "dw_hdmi.h" 34 29 35 30 #define HDMI_EDID_LEN 512 36 31 ··· 47 52 YCbCr422_8B = 0x16, 48 53 YCbCr422_10B = 0x14, 49 54 YCbCr422_12B = 0x12, 50 - }; 51 - 52 - enum imx_hdmi_devtype { 53 - IMX6Q_HDMI, 54 - IMX6DL_HDMI, 55 55 }; 56 56 57 57 static const u16 csc_coeff_default[3][4] = { ··· 101 111 struct hdmi_vmode video_mode; 102 112 }; 103 113 104 - struct imx_hdmi { 114 + struct dw_hdmi { 105 115 struct drm_connector connector; 106 - struct drm_encoder encoder; 116 + struct drm_encoder *encoder; 117 + struct drm_bridge *bridge; 107 118 108 - enum imx_hdmi_devtype dev_type; 119 + enum dw_hdmi_devtype dev_type; 109 120 struct device *dev; 110 121 struct clk *isfr_clk; 111 122 struct clk *iahb_clk; 112 123 113 124 struct hdmi_data_info hdmi_data; 125 + const struct dw_hdmi_plat_data *plat_data; 126 + 114 127 int vic; 115 128 116 129 u8 edid[HDMI_EDID_LEN]; ··· 128 135 129 136 unsigned int sample_rate; 130 137 int ratio; 138 + 139 + void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); 140 + u8 (*read)(struct dw_hdmi *hdmi, int offset); 131 141 }; 132 142 133 - static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di) 143 + static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset) 134 144 { 135 - regmap_update_bits(hdmi->regmap, IOMUXC_GPR3, 136 - IMX6Q_GPR3_HDMI_MUX_CTL_MASK, 137 - ipu_di << IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT); 145 + writel(val, hdmi->regs + (offset << 2)); 138 146 } 139 147 140 - static inline void hdmi_writeb(struct imx_hdmi *hdmi, u8 val, int offset) 148 + static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset) 149 + { 150 + return readl(hdmi->regs + (offset << 2)); 151 + } 152 + 153 + static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset) 141 154 { 142 155 writeb(val, hdmi->regs + offset); 143 156 } 144 157 145 - static inline u8 hdmi_readb(struct imx_hdmi *hdmi, int offset) 158 + static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset) 146 159 { 147 160 return readb(hdmi->regs + offset); 148 161 } 149 162 150 - static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg) 163 + static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset) 164 + { 165 + hdmi->write(hdmi, val, offset); 166 + } 167 + 168 + static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset) 169 + { 170 + return hdmi->read(hdmi, offset); 171 + } 172 + 173 + static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg) 151 174 { 152 175 u8 val = hdmi_readb(hdmi, reg) & ~mask; 153 176 ··· 171 162 hdmi_writeb(hdmi, val, reg); 172 163 } 173 164 174 - static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg, 175 - u8 shift, u8 mask) 165 + static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, 166 + u8 shift, u8 mask) 176 167 { 177 168 hdmi_modb(hdmi, data << shift, mask, reg); 178 169 } 179 170 180 - static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi, 171 + static void hdmi_set_clock_regenerator_n(struct dw_hdmi *hdmi, 181 172 unsigned int value) 182 173 { 183 174 hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1); ··· 188 179 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); 189 180 } 190 181 191 - static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts) 182 + static void hdmi_regenerate_cts(struct dw_hdmi *hdmi, unsigned int cts) 192 183 { 193 184 /* Must be set/cleared first */ 194 185 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); ··· 335 326 return (cts * ratio) / 100; 336 327 } 337 328 338 - static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi, 339 - unsigned long pixel_clk) 329 + static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, 330 + unsigned long pixel_clk) 340 331 { 341 332 unsigned int clk_n, clk_cts; 342 333 ··· 347 338 348 339 if (!clk_cts) { 349 340 dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n", 350 - __func__, pixel_clk); 341 + __func__, pixel_clk); 351 342 return; 352 343 } 353 344 ··· 359 350 hdmi_regenerate_cts(hdmi, clk_cts); 360 351 } 361 352 362 - static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi) 353 + static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi) 363 354 { 364 355 hdmi_set_clk_regenerator(hdmi, 74250000); 365 356 } 366 357 367 - static void hdmi_clk_regenerator_update_pixel_clock(struct imx_hdmi *hdmi) 358 + static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi) 368 359 { 369 360 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock); 370 361 } ··· 376 367 * pin{31~24} <==> G[7:0] 377 368 * pin{15~8} <==> B[7:0] 378 369 */ 379 - static void hdmi_video_sample(struct imx_hdmi *hdmi) 370 + static void hdmi_video_sample(struct dw_hdmi *hdmi) 380 371 { 381 372 int color_format = 0; 382 373 u8 val; ··· 432 423 hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1); 433 424 } 434 425 435 - static int is_color_space_conversion(struct imx_hdmi *hdmi) 426 + static int is_color_space_conversion(struct dw_hdmi *hdmi) 436 427 { 437 428 return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format; 438 429 } 439 430 440 - static int is_color_space_decimation(struct imx_hdmi *hdmi) 431 + static int is_color_space_decimation(struct dw_hdmi *hdmi) 441 432 { 442 433 if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS) 443 434 return 0; ··· 447 438 return 0; 448 439 } 449 440 450 - static int is_color_space_interpolation(struct imx_hdmi *hdmi) 441 + static int is_color_space_interpolation(struct dw_hdmi *hdmi) 451 442 { 452 443 if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS) 453 444 return 0; ··· 457 448 return 0; 458 449 } 459 450 460 - static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi) 451 + static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) 461 452 { 462 453 const u16 (*csc_coeff)[3][4] = &csc_coeff_default; 463 454 unsigned i; ··· 486 477 u16 coeff_b = (*csc_coeff)[1][i]; 487 478 u16 coeff_c = (*csc_coeff)[2][i]; 488 479 489 - hdmi_writeb(hdmi, coeff_a & 0xff, 490 - HDMI_CSC_COEF_A1_LSB + i * 2); 480 + hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2); 491 481 hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2); 492 482 hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2); 493 483 hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2); 494 - hdmi_writeb(hdmi, coeff_c & 0xff, 495 - HDMI_CSC_COEF_C1_LSB + i * 2); 484 + hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2); 496 485 hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2); 497 486 } 498 487 ··· 498 491 HDMI_CSC_SCALE); 499 492 } 500 493 501 - static void hdmi_video_csc(struct imx_hdmi *hdmi) 494 + static void hdmi_video_csc(struct dw_hdmi *hdmi) 502 495 { 503 496 int color_depth = 0; 504 497 int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE; ··· 526 519 hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK, 527 520 HDMI_CSC_SCALE); 528 521 529 - imx_hdmi_update_csc_coeffs(hdmi); 522 + dw_hdmi_update_csc_coeffs(hdmi); 530 523 } 531 524 532 525 /* ··· 534 527 * for example, if input is YCC422 mode or repeater is used, 535 528 * data should be repacked this module can be bypassed. 536 529 */ 537 - static void hdmi_video_packetize(struct imx_hdmi *hdmi) 530 + static void hdmi_video_packetize(struct dw_hdmi *hdmi) 538 531 { 539 532 unsigned int color_depth = 0; 540 533 unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit; ··· 542 535 struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data; 543 536 u8 val, vp_conf; 544 537 545 - if (hdmi_data->enc_out_format == RGB 546 - || hdmi_data->enc_out_format == YCBCR444) { 547 - if (!hdmi_data->enc_color_depth) 538 + if (hdmi_data->enc_out_format == RGB || 539 + hdmi_data->enc_out_format == YCBCR444) { 540 + if (!hdmi_data->enc_color_depth) { 548 541 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; 549 - else if (hdmi_data->enc_color_depth == 8) { 542 + } else if (hdmi_data->enc_color_depth == 8) { 550 543 color_depth = 4; 551 544 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; 552 - } else if (hdmi_data->enc_color_depth == 10) 545 + } else if (hdmi_data->enc_color_depth == 10) { 553 546 color_depth = 5; 554 - else if (hdmi_data->enc_color_depth == 12) 547 + } else if (hdmi_data->enc_color_depth == 12) { 555 548 color_depth = 6; 556 - else if (hdmi_data->enc_color_depth == 16) 549 + } else if (hdmi_data->enc_color_depth == 16) { 557 550 color_depth = 7; 558 - else 551 + } else { 559 552 return; 553 + } 560 554 } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) { 561 555 if (!hdmi_data->enc_color_depth || 562 556 hdmi_data->enc_color_depth == 8) ··· 569 561 else 570 562 return; 571 563 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422; 572 - } else 564 + } else { 573 565 return; 566 + } 574 567 575 568 /* set the packetizer registers */ 576 569 val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) & ··· 631 622 HDMI_VP_CONF); 632 623 } 633 624 634 - static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi, 635 - unsigned char bit) 625 + static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, 626 + unsigned char bit) 636 627 { 637 628 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET, 638 629 HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0); 639 630 } 640 631 641 - static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi, 642 - unsigned char bit) 632 + static inline void hdmi_phy_test_enable(struct dw_hdmi *hdmi, 633 + unsigned char bit) 643 634 { 644 635 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET, 645 636 HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0); 646 637 } 647 638 648 - static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi, 649 - unsigned char bit) 639 + static inline void hdmi_phy_test_clock(struct dw_hdmi *hdmi, 640 + unsigned char bit) 650 641 { 651 642 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET, 652 643 HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0); 653 644 } 654 645 655 - static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi, 656 - unsigned char bit) 646 + static inline void hdmi_phy_test_din(struct dw_hdmi *hdmi, 647 + unsigned char bit) 657 648 { 658 649 hdmi_writeb(hdmi, bit, HDMI_PHY_TST1); 659 650 } 660 651 661 - static inline void hdmi_phy_test_dout(struct imx_hdmi *hdmi, 662 - unsigned char bit) 652 + static inline void hdmi_phy_test_dout(struct dw_hdmi *hdmi, 653 + unsigned char bit) 663 654 { 664 655 hdmi_writeb(hdmi, bit, HDMI_PHY_TST2); 665 656 } 666 657 667 - static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int msec) 658 + static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec) 668 659 { 669 - while ((hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) { 660 + u32 val; 661 + 662 + while ((val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) { 670 663 if (msec-- == 0) 671 664 return false; 672 665 udelay(1000); 673 666 } 667 + hdmi_writeb(hdmi, val, HDMI_IH_I2CMPHY_STAT0); 668 + 674 669 return true; 675 670 } 676 671 677 - static void __hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data, 678 - unsigned char addr) 672 + static void __hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, 673 + unsigned char addr) 679 674 { 680 675 hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0); 681 676 hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR); 682 677 hdmi_writeb(hdmi, (unsigned char)(data >> 8), 683 - HDMI_PHY_I2CM_DATAO_1_ADDR); 678 + HDMI_PHY_I2CM_DATAO_1_ADDR); 684 679 hdmi_writeb(hdmi, (unsigned char)(data >> 0), 685 - HDMI_PHY_I2CM_DATAO_0_ADDR); 680 + HDMI_PHY_I2CM_DATAO_0_ADDR); 686 681 hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE, 687 - HDMI_PHY_I2CM_OPERATION_ADDR); 682 + HDMI_PHY_I2CM_OPERATION_ADDR); 688 683 hdmi_phy_wait_i2c_done(hdmi, 1000); 689 684 } 690 685 691 - static int hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data, 692 - unsigned char addr) 686 + static int hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, 687 + unsigned char addr) 693 688 { 694 689 __hdmi_phy_i2c_write(hdmi, data, addr); 695 690 return 0; 696 691 } 697 692 698 - static void imx_hdmi_phy_enable_power(struct imx_hdmi *hdmi, u8 enable) 693 + static void dw_hdmi_phy_enable_power(struct dw_hdmi *hdmi, u8 enable) 699 694 { 700 695 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 701 696 HDMI_PHY_CONF0_PDZ_OFFSET, 702 697 HDMI_PHY_CONF0_PDZ_MASK); 703 698 } 704 699 705 - static void imx_hdmi_phy_enable_tmds(struct imx_hdmi *hdmi, u8 enable) 700 + static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable) 706 701 { 707 702 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 708 703 HDMI_PHY_CONF0_ENTMDS_OFFSET, 709 704 HDMI_PHY_CONF0_ENTMDS_MASK); 710 705 } 711 706 712 - static void imx_hdmi_phy_gen2_pddq(struct imx_hdmi *hdmi, u8 enable) 707 + static void dw_hdmi_phy_enable_spare(struct dw_hdmi *hdmi, u8 enable) 708 + { 709 + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 710 + HDMI_PHY_CONF0_SPARECTRL_OFFSET, 711 + HDMI_PHY_CONF0_SPARECTRL_MASK); 712 + } 713 + 714 + static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable) 713 715 { 714 716 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 715 717 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET, 716 718 HDMI_PHY_CONF0_GEN2_PDDQ_MASK); 717 719 } 718 720 719 - static void imx_hdmi_phy_gen2_txpwron(struct imx_hdmi *hdmi, u8 enable) 721 + static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable) 720 722 { 721 723 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 722 724 HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET, 723 725 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK); 724 726 } 725 727 726 - static void imx_hdmi_phy_sel_data_en_pol(struct imx_hdmi *hdmi, u8 enable) 728 + static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable) 727 729 { 728 730 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 729 731 HDMI_PHY_CONF0_SELDATAENPOL_OFFSET, 730 732 HDMI_PHY_CONF0_SELDATAENPOL_MASK); 731 733 } 732 734 733 - static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable) 735 + static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable) 734 736 { 735 737 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 736 738 HDMI_PHY_CONF0_SELDIPIF_OFFSET, 737 739 HDMI_PHY_CONF0_SELDIPIF_MASK); 738 740 } 739 741 740 - enum { 741 - RES_8, 742 - RES_10, 743 - RES_12, 744 - RES_MAX, 745 - }; 746 - 747 - struct mpll_config { 748 - unsigned long mpixelclock; 749 - struct { 750 - u16 cpce; 751 - u16 gmp; 752 - } res[RES_MAX]; 753 - }; 754 - 755 - static const struct mpll_config mpll_config[] = { 756 - { 757 - 45250000, { 758 - { 0x01e0, 0x0000 }, 759 - { 0x21e1, 0x0000 }, 760 - { 0x41e2, 0x0000 } 761 - }, 762 - }, { 763 - 92500000, { 764 - { 0x0140, 0x0005 }, 765 - { 0x2141, 0x0005 }, 766 - { 0x4142, 0x0005 }, 767 - }, 768 - }, { 769 - 148500000, { 770 - { 0x00a0, 0x000a }, 771 - { 0x20a1, 0x000a }, 772 - { 0x40a2, 0x000a }, 773 - }, 774 - }, { 775 - ~0UL, { 776 - { 0x00a0, 0x000a }, 777 - { 0x2001, 0x000f }, 778 - { 0x4002, 0x000f }, 779 - }, 780 - } 781 - }; 782 - 783 - struct curr_ctrl { 784 - unsigned long mpixelclock; 785 - u16 curr[RES_MAX]; 786 - }; 787 - 788 - static const struct curr_ctrl curr_ctrl[] = { 789 - /* pixelclk bpp8 bpp10 bpp12 */ 790 - { 791 - 54000000, { 0x091c, 0x091c, 0x06dc }, 792 - }, { 793 - 58400000, { 0x091c, 0x06dc, 0x06dc }, 794 - }, { 795 - 72000000, { 0x06dc, 0x06dc, 0x091c }, 796 - }, { 797 - 74250000, { 0x06dc, 0x0b5c, 0x091c }, 798 - }, { 799 - 118800000, { 0x091c, 0x091c, 0x06dc }, 800 - }, { 801 - 216000000, { 0x06dc, 0x0b5c, 0x091c }, 802 - } 803 - }; 804 - 805 - static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep, 742 + static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep, 806 743 unsigned char res, int cscon) 807 744 { 808 745 unsigned res_idx, i; 809 746 u8 val, msec; 747 + const struct dw_hdmi_mpll_config *mpll_config = 748 + hdmi->plat_data->mpll_cfg; 749 + const struct dw_hdmi_curr_ctrl *curr_ctrl = hdmi->plat_data->cur_ctr; 750 + const struct dw_hdmi_sym_term *sym_term = hdmi->plat_data->sym_term; 810 751 811 752 if (prep) 812 753 return -EINVAL; ··· 764 805 switch (res) { 765 806 case 0: /* color resolution 0 is 8 bit colour depth */ 766 807 case 8: 767 - res_idx = RES_8; 808 + res_idx = DW_HDMI_RES_8; 768 809 break; 769 810 case 10: 770 - res_idx = RES_10; 811 + res_idx = DW_HDMI_RES_10; 771 812 break; 772 813 case 12: 773 - res_idx = RES_12; 814 + res_idx = DW_HDMI_RES_12; 774 815 break; 775 816 default: 776 817 return -EINVAL; ··· 785 826 hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL); 786 827 787 828 /* gen2 tx power off */ 788 - imx_hdmi_phy_gen2_txpwron(hdmi, 0); 829 + dw_hdmi_phy_gen2_txpwron(hdmi, 0); 789 830 790 831 /* gen2 pddq */ 791 - imx_hdmi_phy_gen2_pddq(hdmi, 1); 832 + dw_hdmi_phy_gen2_pddq(hdmi, 1); 792 833 793 834 /* PHY reset */ 794 835 hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ); ··· 798 839 799 840 hdmi_phy_test_clear(hdmi, 1); 800 841 hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, 801 - HDMI_PHY_I2CM_SLAVE_ADDR); 842 + HDMI_PHY_I2CM_SLAVE_ADDR); 802 843 hdmi_phy_test_clear(hdmi, 0); 803 844 804 845 /* PLL/MPLL Cfg - always match on final entry */ 805 - for (i = 0; i < ARRAY_SIZE(mpll_config) - 1; i++) 846 + for (i = 0; mpll_config[i].mpixelclock != (~0UL); i++) 806 847 if (hdmi->hdmi_data.video_mode.mpixelclock <= 807 848 mpll_config[i].mpixelclock) 808 849 break; ··· 810 851 hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06); 811 852 hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15); 812 853 813 - for (i = 0; i < ARRAY_SIZE(curr_ctrl); i++) 854 + for (i = 0; curr_ctrl[i].mpixelclock != (~0UL); i++) 814 855 if (hdmi->hdmi_data.video_mode.mpixelclock <= 815 856 curr_ctrl[i].mpixelclock) 816 857 break; 817 858 818 - if (i >= ARRAY_SIZE(curr_ctrl)) { 819 - dev_err(hdmi->dev, 820 - "Pixel clock %d - unsupported by HDMI\n", 821 - hdmi->hdmi_data.video_mode.mpixelclock); 859 + if (curr_ctrl[i].mpixelclock == (~0UL)) { 860 + dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n", 861 + hdmi->hdmi_data.video_mode.mpixelclock); 822 862 return -EINVAL; 823 863 } 824 864 ··· 826 868 827 869 hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */ 828 870 hdmi_phy_i2c_write(hdmi, 0x0006, 0x17); 871 + 872 + for (i = 0; sym_term[i].mpixelclock != (~0UL); i++) 873 + if (hdmi->hdmi_data.video_mode.mpixelclock <= 874 + sym_term[i].mpixelclock) 875 + break; 876 + 829 877 /* RESISTANCE TERM 133Ohm Cfg */ 830 - hdmi_phy_i2c_write(hdmi, 0x0005, 0x19); /* TXTERM */ 878 + hdmi_phy_i2c_write(hdmi, sym_term[i].term, 0x19); /* TXTERM */ 831 879 /* PREEMP Cgf 0.00 */ 832 - hdmi_phy_i2c_write(hdmi, 0x800d, 0x09); /* CKSYMTXCTRL */ 880 + hdmi_phy_i2c_write(hdmi, sym_term[i].sym_ctr, 0x09); /* CKSYMTXCTRL */ 881 + 833 882 /* TX/CK LVL 10 */ 834 883 hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */ 835 884 /* REMOVE CLK TERM */ 836 885 hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */ 837 886 838 - imx_hdmi_phy_enable_power(hdmi, 1); 887 + dw_hdmi_phy_enable_power(hdmi, 1); 839 888 840 889 /* toggle TMDS enable */ 841 - imx_hdmi_phy_enable_tmds(hdmi, 0); 842 - imx_hdmi_phy_enable_tmds(hdmi, 1); 890 + dw_hdmi_phy_enable_tmds(hdmi, 0); 891 + dw_hdmi_phy_enable_tmds(hdmi, 1); 843 892 844 893 /* gen2 tx power on */ 845 - imx_hdmi_phy_gen2_txpwron(hdmi, 1); 846 - imx_hdmi_phy_gen2_pddq(hdmi, 0); 894 + dw_hdmi_phy_gen2_txpwron(hdmi, 1); 895 + dw_hdmi_phy_gen2_pddq(hdmi, 0); 896 + 897 + if (hdmi->dev_type == RK3288_HDMI) 898 + dw_hdmi_phy_enable_spare(hdmi, 1); 847 899 848 900 /*Wait for PHY PLL lock */ 849 901 msec = 5; ··· 874 906 return 0; 875 907 } 876 908 877 - static int imx_hdmi_phy_init(struct imx_hdmi *hdmi) 909 + static int dw_hdmi_phy_init(struct dw_hdmi *hdmi) 878 910 { 879 911 int i, ret; 880 912 bool cscon = false; ··· 885 917 886 918 /* HDMI Phy spec says to do the phy initialization sequence twice */ 887 919 for (i = 0; i < 2; i++) { 888 - imx_hdmi_phy_sel_data_en_pol(hdmi, 1); 889 - imx_hdmi_phy_sel_interface_control(hdmi, 0); 890 - imx_hdmi_phy_enable_tmds(hdmi, 0); 891 - imx_hdmi_phy_enable_power(hdmi, 0); 920 + dw_hdmi_phy_sel_data_en_pol(hdmi, 1); 921 + dw_hdmi_phy_sel_interface_control(hdmi, 0); 922 + dw_hdmi_phy_enable_tmds(hdmi, 0); 923 + dw_hdmi_phy_enable_power(hdmi, 0); 892 924 893 925 /* Enable CSC */ 894 926 ret = hdmi_phy_configure(hdmi, 0, 8, cscon); ··· 900 932 return 0; 901 933 } 902 934 903 - static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi) 935 + static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) 904 936 { 905 937 u8 de; 906 938 ··· 919 951 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1); 920 952 } 921 953 922 - static void hdmi_config_AVI(struct imx_hdmi *hdmi) 954 + static void hdmi_config_AVI(struct dw_hdmi *hdmi) 923 955 { 924 956 u8 val, pix_fmt, under_scan; 925 957 u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry; ··· 1013 1045 hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB1); 1014 1046 } 1015 1047 1016 - static void hdmi_av_composer(struct imx_hdmi *hdmi, 1048 + static void hdmi_av_composer(struct dw_hdmi *hdmi, 1017 1049 const struct drm_display_mode *mode) 1018 1050 { 1019 1051 u8 inv_val; ··· 1097 1129 hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH); 1098 1130 } 1099 1131 1100 - static void imx_hdmi_phy_disable(struct imx_hdmi *hdmi) 1132 + static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi) 1101 1133 { 1102 1134 if (!hdmi->phy_enabled) 1103 1135 return; 1104 1136 1105 - imx_hdmi_phy_enable_tmds(hdmi, 0); 1106 - imx_hdmi_phy_enable_power(hdmi, 0); 1137 + dw_hdmi_phy_enable_tmds(hdmi, 0); 1138 + dw_hdmi_phy_enable_power(hdmi, 0); 1107 1139 1108 1140 hdmi->phy_enabled = false; 1109 1141 } 1110 1142 1111 1143 /* HDMI Initialization Step B.4 */ 1112 - static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi) 1144 + static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) 1113 1145 { 1114 1146 u8 clkdis; 1115 1147 ··· 1138 1170 } 1139 1171 } 1140 1172 1141 - static void hdmi_enable_audio_clk(struct imx_hdmi *hdmi) 1173 + static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi) 1142 1174 { 1143 1175 hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS); 1144 1176 } 1145 1177 1146 1178 /* Workaround to clear the overflow condition */ 1147 - static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi) 1179 + static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) 1148 1180 { 1149 1181 int count; 1150 1182 u8 val; ··· 1162 1194 hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF); 1163 1195 } 1164 1196 1165 - static void hdmi_enable_overflow_interrupts(struct imx_hdmi *hdmi) 1197 + static void hdmi_enable_overflow_interrupts(struct dw_hdmi *hdmi) 1166 1198 { 1167 1199 hdmi_writeb(hdmi, 0, HDMI_FC_MASK2); 1168 1200 hdmi_writeb(hdmi, 0, HDMI_IH_MUTE_FC_STAT2); 1169 1201 } 1170 1202 1171 - static void hdmi_disable_overflow_interrupts(struct imx_hdmi *hdmi) 1203 + static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi) 1172 1204 { 1173 1205 hdmi_writeb(hdmi, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK, 1174 1206 HDMI_IH_MUTE_FC_STAT2); 1175 1207 } 1176 1208 1177 - static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode) 1209 + static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) 1178 1210 { 1179 1211 int ret; 1180 1212 ··· 1191 1223 } 1192 1224 1193 1225 if ((hdmi->vic == 6) || (hdmi->vic == 7) || 1194 - (hdmi->vic == 21) || (hdmi->vic == 22) || 1195 - (hdmi->vic == 2) || (hdmi->vic == 3) || 1196 - (hdmi->vic == 17) || (hdmi->vic == 18)) 1226 + (hdmi->vic == 21) || (hdmi->vic == 22) || 1227 + (hdmi->vic == 2) || (hdmi->vic == 3) || 1228 + (hdmi->vic == 17) || (hdmi->vic == 18)) 1197 1229 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601; 1198 1230 else 1199 1231 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; 1200 1232 1201 1233 if ((hdmi->vic == 10) || (hdmi->vic == 11) || 1202 - (hdmi->vic == 12) || (hdmi->vic == 13) || 1203 - (hdmi->vic == 14) || (hdmi->vic == 15) || 1204 - (hdmi->vic == 25) || (hdmi->vic == 26) || 1205 - (hdmi->vic == 27) || (hdmi->vic == 28) || 1206 - (hdmi->vic == 29) || (hdmi->vic == 30) || 1207 - (hdmi->vic == 35) || (hdmi->vic == 36) || 1208 - (hdmi->vic == 37) || (hdmi->vic == 38)) 1234 + (hdmi->vic == 12) || (hdmi->vic == 13) || 1235 + (hdmi->vic == 14) || (hdmi->vic == 15) || 1236 + (hdmi->vic == 25) || (hdmi->vic == 26) || 1237 + (hdmi->vic == 27) || (hdmi->vic == 28) || 1238 + (hdmi->vic == 29) || (hdmi->vic == 30) || 1239 + (hdmi->vic == 35) || (hdmi->vic == 36) || 1240 + (hdmi->vic == 37) || (hdmi->vic == 38)) 1209 1241 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 1; 1210 1242 else 1211 1243 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; ··· 1226 1258 hdmi_av_composer(hdmi, mode); 1227 1259 1228 1260 /* HDMI Initializateion Step B.2 */ 1229 - ret = imx_hdmi_phy_init(hdmi); 1261 + ret = dw_hdmi_phy_init(hdmi); 1230 1262 if (ret) 1231 1263 return ret; 1232 1264 1233 1265 /* HDMI Initialization Step B.3 */ 1234 - imx_hdmi_enable_video_path(hdmi); 1266 + dw_hdmi_enable_video_path(hdmi); 1235 1267 1236 1268 /* not for DVI mode */ 1237 - if (hdmi->hdmi_data.video_mode.mdvi) 1269 + if (hdmi->hdmi_data.video_mode.mdvi) { 1238 1270 dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); 1239 - else { 1271 + } else { 1240 1272 dev_dbg(hdmi->dev, "%s CEA mode\n", __func__); 1241 1273 1242 1274 /* HDMI Initialization Step E - Configure audio */ ··· 1252 1284 hdmi_video_sample(hdmi); 1253 1285 hdmi_tx_hdcp_config(hdmi); 1254 1286 1255 - imx_hdmi_clear_overflow(hdmi); 1287 + dw_hdmi_clear_overflow(hdmi); 1256 1288 if (hdmi->cable_plugin && !hdmi->hdmi_data.video_mode.mdvi) 1257 1289 hdmi_enable_overflow_interrupts(hdmi); 1258 1290 ··· 1260 1292 } 1261 1293 1262 1294 /* Wait until we are registered to enable interrupts */ 1263 - static int imx_hdmi_fb_registered(struct imx_hdmi *hdmi) 1295 + static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi) 1264 1296 { 1265 1297 hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, 1266 1298 HDMI_PHY_I2CM_INT_ADDR); ··· 1278 1310 return 0; 1279 1311 } 1280 1312 1281 - static void initialize_hdmi_ih_mutes(struct imx_hdmi *hdmi) 1313 + static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi) 1282 1314 { 1283 1315 u8 ih_mute; 1284 1316 ··· 1330 1362 hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE); 1331 1363 } 1332 1364 1333 - static void imx_hdmi_poweron(struct imx_hdmi *hdmi) 1365 + static void dw_hdmi_poweron(struct dw_hdmi *hdmi) 1334 1366 { 1335 - imx_hdmi_setup(hdmi, &hdmi->previous_mode); 1367 + dw_hdmi_setup(hdmi, &hdmi->previous_mode); 1336 1368 } 1337 1369 1338 - static void imx_hdmi_poweroff(struct imx_hdmi *hdmi) 1370 + static void dw_hdmi_poweroff(struct dw_hdmi *hdmi) 1339 1371 { 1340 - imx_hdmi_phy_disable(hdmi); 1372 + dw_hdmi_phy_disable(hdmi); 1341 1373 } 1342 1374 1343 - static enum drm_connector_status imx_hdmi_connector_detect(struct drm_connector 1344 - *connector, bool force) 1375 + static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge, 1376 + struct drm_display_mode *orig_mode, 1377 + struct drm_display_mode *mode) 1345 1378 { 1346 - struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi, 1379 + struct dw_hdmi *hdmi = bridge->driver_private; 1380 + 1381 + dw_hdmi_setup(hdmi, mode); 1382 + 1383 + /* Store the display mode for plugin/DKMS poweron events */ 1384 + memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); 1385 + } 1386 + 1387 + static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, 1388 + const struct drm_display_mode *mode, 1389 + struct drm_display_mode *adjusted_mode) 1390 + { 1391 + return true; 1392 + } 1393 + 1394 + static void dw_hdmi_bridge_disable(struct drm_bridge *bridge) 1395 + { 1396 + struct dw_hdmi *hdmi = bridge->driver_private; 1397 + 1398 + dw_hdmi_poweroff(hdmi); 1399 + } 1400 + 1401 + static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) 1402 + { 1403 + struct dw_hdmi *hdmi = bridge->driver_private; 1404 + 1405 + dw_hdmi_poweron(hdmi); 1406 + } 1407 + 1408 + static void dw_hdmi_bridge_destroy(struct drm_bridge *bridge) 1409 + { 1410 + drm_bridge_cleanup(bridge); 1411 + kfree(bridge); 1412 + } 1413 + 1414 + static void dw_hdmi_bridge_nop(struct drm_bridge *bridge) 1415 + { 1416 + /* do nothing */ 1417 + } 1418 + 1419 + static enum drm_connector_status 1420 + dw_hdmi_connector_detect(struct drm_connector *connector, bool force) 1421 + { 1422 + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, 1347 1423 connector); 1348 1424 1349 1425 return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? 1350 1426 connector_status_connected : connector_status_disconnected; 1351 1427 } 1352 1428 1353 - static int imx_hdmi_connector_get_modes(struct drm_connector *connector) 1429 + static int dw_hdmi_connector_get_modes(struct drm_connector *connector) 1354 1430 { 1355 - struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi, 1431 + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, 1356 1432 connector); 1357 1433 struct edid *edid; 1358 1434 int ret; ··· 1419 1407 return 0; 1420 1408 } 1421 1409 1422 - static struct drm_encoder *imx_hdmi_connector_best_encoder(struct drm_connector 1410 + static enum drm_mode_status 1411 + dw_hdmi_connector_mode_valid(struct drm_connector *connector, 1412 + struct drm_display_mode *mode) 1413 + { 1414 + struct dw_hdmi *hdmi = container_of(connector, 1415 + struct dw_hdmi, connector); 1416 + enum drm_mode_status mode_status = MODE_OK; 1417 + 1418 + if (hdmi->plat_data->mode_valid) 1419 + mode_status = hdmi->plat_data->mode_valid(connector, mode); 1420 + 1421 + return mode_status; 1422 + } 1423 + 1424 + static struct drm_encoder *dw_hdmi_connector_best_encoder(struct drm_connector 1423 1425 *connector) 1424 1426 { 1425 - struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi, 1427 + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, 1426 1428 connector); 1427 1429 1428 - return &hdmi->encoder; 1430 + return hdmi->encoder; 1429 1431 } 1430 1432 1431 - static void imx_hdmi_encoder_mode_set(struct drm_encoder *encoder, 1432 - struct drm_display_mode *mode, 1433 - struct drm_display_mode *adjusted_mode) 1433 + static void dw_hdmi_connector_destroy(struct drm_connector *connector) 1434 1434 { 1435 - struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); 1436 - 1437 - imx_hdmi_setup(hdmi, mode); 1438 - 1439 - /* Store the display mode for plugin/DKMS poweron events */ 1440 - memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); 1435 + drm_connector_unregister(connector); 1436 + drm_connector_cleanup(connector); 1441 1437 } 1442 1438 1443 - static bool imx_hdmi_encoder_mode_fixup(struct drm_encoder *encoder, 1444 - const struct drm_display_mode *mode, 1445 - struct drm_display_mode *adjusted_mode) 1446 - { 1447 - return true; 1448 - } 1449 - 1450 - static void imx_hdmi_encoder_disable(struct drm_encoder *encoder) 1451 - { 1452 - } 1453 - 1454 - static void imx_hdmi_encoder_dpms(struct drm_encoder *encoder, int mode) 1455 - { 1456 - struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); 1457 - 1458 - if (mode) 1459 - imx_hdmi_poweroff(hdmi); 1460 - else 1461 - imx_hdmi_poweron(hdmi); 1462 - } 1463 - 1464 - static void imx_hdmi_encoder_prepare(struct drm_encoder *encoder) 1465 - { 1466 - struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); 1467 - 1468 - imx_hdmi_poweroff(hdmi); 1469 - imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24); 1470 - } 1471 - 1472 - static void imx_hdmi_encoder_commit(struct drm_encoder *encoder) 1473 - { 1474 - struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); 1475 - int mux = imx_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder); 1476 - 1477 - imx_hdmi_set_ipu_di_mux(hdmi, mux); 1478 - 1479 - imx_hdmi_poweron(hdmi); 1480 - } 1481 - 1482 - static struct drm_encoder_funcs imx_hdmi_encoder_funcs = { 1483 - .destroy = imx_drm_encoder_destroy, 1484 - }; 1485 - 1486 - static struct drm_encoder_helper_funcs imx_hdmi_encoder_helper_funcs = { 1487 - .dpms = imx_hdmi_encoder_dpms, 1488 - .prepare = imx_hdmi_encoder_prepare, 1489 - .commit = imx_hdmi_encoder_commit, 1490 - .mode_set = imx_hdmi_encoder_mode_set, 1491 - .mode_fixup = imx_hdmi_encoder_mode_fixup, 1492 - .disable = imx_hdmi_encoder_disable, 1493 - }; 1494 - 1495 - static struct drm_connector_funcs imx_hdmi_connector_funcs = { 1439 + static struct drm_connector_funcs dw_hdmi_connector_funcs = { 1496 1440 .dpms = drm_helper_connector_dpms, 1497 1441 .fill_modes = drm_helper_probe_single_connector_modes, 1498 - .detect = imx_hdmi_connector_detect, 1499 - .destroy = imx_drm_connector_destroy, 1442 + .detect = dw_hdmi_connector_detect, 1443 + .destroy = dw_hdmi_connector_destroy, 1500 1444 }; 1501 1445 1502 - static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = { 1503 - .get_modes = imx_hdmi_connector_get_modes, 1504 - .best_encoder = imx_hdmi_connector_best_encoder, 1446 + static struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = { 1447 + .get_modes = dw_hdmi_connector_get_modes, 1448 + .mode_valid = dw_hdmi_connector_mode_valid, 1449 + .best_encoder = dw_hdmi_connector_best_encoder, 1505 1450 }; 1506 1451 1507 - static irqreturn_t imx_hdmi_hardirq(int irq, void *dev_id) 1452 + struct drm_bridge_funcs dw_hdmi_bridge_funcs = { 1453 + .enable = dw_hdmi_bridge_enable, 1454 + .disable = dw_hdmi_bridge_disable, 1455 + .pre_enable = dw_hdmi_bridge_nop, 1456 + .post_disable = dw_hdmi_bridge_nop, 1457 + .mode_set = dw_hdmi_bridge_mode_set, 1458 + .mode_fixup = dw_hdmi_bridge_mode_fixup, 1459 + .destroy = dw_hdmi_bridge_destroy, 1460 + }; 1461 + 1462 + static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) 1508 1463 { 1509 - struct imx_hdmi *hdmi = dev_id; 1464 + struct dw_hdmi *hdmi = dev_id; 1510 1465 u8 intr_stat; 1511 1466 1512 1467 intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); ··· 1483 1504 return intr_stat ? IRQ_WAKE_THREAD : IRQ_NONE; 1484 1505 } 1485 1506 1486 - static irqreturn_t imx_hdmi_irq(int irq, void *dev_id) 1507 + static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) 1487 1508 { 1488 - struct imx_hdmi *hdmi = dev_id; 1509 + struct dw_hdmi *hdmi = dev_id; 1489 1510 u8 intr_stat; 1490 1511 u8 phy_int_pol; 1491 1512 ··· 1499 1520 1500 1521 hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0); 1501 1522 1502 - imx_hdmi_poweron(hdmi); 1523 + dw_hdmi_poweron(hdmi); 1503 1524 } else { 1504 1525 dev_dbg(hdmi->dev, "EVENT=plugout\n"); 1505 1526 1506 1527 hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD, 1507 - HDMI_PHY_POL0); 1528 + HDMI_PHY_POL0); 1508 1529 1509 - imx_hdmi_poweroff(hdmi); 1530 + dw_hdmi_poweroff(hdmi); 1510 1531 } 1511 1532 drm_helper_hpd_irq_event(hdmi->connector.dev); 1512 1533 } ··· 1517 1538 return IRQ_HANDLED; 1518 1539 } 1519 1540 1520 - static int imx_hdmi_register(struct drm_device *drm, struct imx_hdmi *hdmi) 1541 + static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi) 1521 1542 { 1543 + struct drm_encoder *encoder = hdmi->encoder; 1544 + struct drm_bridge *bridge; 1522 1545 int ret; 1523 1546 1524 - ret = imx_drm_encoder_parse_of(drm, &hdmi->encoder, 1525 - hdmi->dev->of_node); 1526 - if (ret) 1527 - return ret; 1547 + bridge = devm_kzalloc(drm->dev, sizeof(*bridge), GFP_KERNEL); 1548 + if (!bridge) { 1549 + DRM_ERROR("Failed to allocate drm bridge\n"); 1550 + return -ENOMEM; 1551 + } 1528 1552 1553 + hdmi->bridge = bridge; 1554 + bridge->driver_private = hdmi; 1555 + 1556 + ret = drm_bridge_init(drm, bridge, &dw_hdmi_bridge_funcs); 1557 + if (ret) { 1558 + DRM_ERROR("Failed to initialize bridge with drm\n"); 1559 + return -EINVAL; 1560 + } 1561 + 1562 + encoder->bridge = bridge; 1529 1563 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD; 1530 1564 1531 - drm_encoder_helper_add(&hdmi->encoder, &imx_hdmi_encoder_helper_funcs); 1532 - drm_encoder_init(drm, &hdmi->encoder, &imx_hdmi_encoder_funcs, 1533 - DRM_MODE_ENCODER_TMDS); 1534 - 1535 1565 drm_connector_helper_add(&hdmi->connector, 1536 - &imx_hdmi_connector_helper_funcs); 1537 - drm_connector_init(drm, &hdmi->connector, &imx_hdmi_connector_funcs, 1566 + &dw_hdmi_connector_helper_funcs); 1567 + drm_connector_init(drm, &hdmi->connector, &dw_hdmi_connector_funcs, 1538 1568 DRM_MODE_CONNECTOR_HDMIA); 1539 1569 1540 - hdmi->connector.encoder = &hdmi->encoder; 1570 + hdmi->connector.encoder = encoder; 1541 1571 1542 - drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder); 1572 + drm_mode_connector_attach_encoder(&hdmi->connector, encoder); 1543 1573 1544 1574 return 0; 1545 1575 } 1546 1576 1547 - static struct platform_device_id imx_hdmi_devtype[] = { 1548 - { 1549 - .name = "imx6q-hdmi", 1550 - .driver_data = IMX6Q_HDMI, 1551 - }, { 1552 - .name = "imx6dl-hdmi", 1553 - .driver_data = IMX6DL_HDMI, 1554 - }, { /* sentinel */ } 1555 - }; 1556 - MODULE_DEVICE_TABLE(platform, imx_hdmi_devtype); 1557 - 1558 - static const struct of_device_id imx_hdmi_dt_ids[] = { 1559 - { .compatible = "fsl,imx6q-hdmi", .data = &imx_hdmi_devtype[IMX6Q_HDMI], }, 1560 - { .compatible = "fsl,imx6dl-hdmi", .data = &imx_hdmi_devtype[IMX6DL_HDMI], }, 1561 - { /* sentinel */ } 1562 - }; 1563 - MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids); 1564 - 1565 - static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) 1577 + int dw_hdmi_bind(struct device *dev, struct device *master, 1578 + void *data, struct drm_encoder *encoder, 1579 + struct resource *iores, int irq, 1580 + const struct dw_hdmi_plat_data *plat_data) 1566 1581 { 1567 - struct platform_device *pdev = to_platform_device(dev); 1568 - const struct of_device_id *of_id = 1569 - of_match_device(imx_hdmi_dt_ids, dev); 1570 1582 struct drm_device *drm = data; 1571 1583 struct device_node *np = dev->of_node; 1572 1584 struct device_node *ddc_node; 1573 - struct imx_hdmi *hdmi; 1574 - struct resource *iores; 1575 - int ret, irq; 1585 + struct dw_hdmi *hdmi; 1586 + int ret; 1587 + u32 val = 1; 1576 1588 1577 1589 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); 1578 1590 if (!hdmi) 1579 1591 return -ENOMEM; 1580 1592 1593 + hdmi->plat_data = plat_data; 1581 1594 hdmi->dev = dev; 1595 + hdmi->dev_type = plat_data->dev_type; 1582 1596 hdmi->sample_rate = 48000; 1583 1597 hdmi->ratio = 100; 1598 + hdmi->encoder = encoder; 1584 1599 1585 - if (of_id) { 1586 - const struct platform_device_id *device_id = of_id->data; 1600 + of_property_read_u32(np, "reg-io-width", &val); 1587 1601 1588 - hdmi->dev_type = device_id->driver_data; 1602 + switch (val) { 1603 + case 4: 1604 + hdmi->write = dw_hdmi_writel; 1605 + hdmi->read = dw_hdmi_readl; 1606 + break; 1607 + case 1: 1608 + hdmi->write = dw_hdmi_writeb; 1609 + hdmi->read = dw_hdmi_readb; 1610 + break; 1611 + default: 1612 + dev_err(dev, "reg-io-width must be 1 or 4\n"); 1613 + return -EINVAL; 1589 1614 } 1590 1615 1591 1616 ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); 1592 1617 if (ddc_node) { 1593 1618 hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); 1594 - if (!hdmi->ddc) 1595 - dev_dbg(hdmi->dev, "failed to read ddc node\n"); 1596 - 1597 1619 of_node_put(ddc_node); 1620 + if (!hdmi->ddc) { 1621 + dev_dbg(hdmi->dev, "failed to read ddc node\n"); 1622 + return -EPROBE_DEFER; 1623 + } 1624 + 1598 1625 } else { 1599 1626 dev_dbg(hdmi->dev, "no ddc property found\n"); 1600 1627 } 1601 1628 1602 - irq = platform_get_irq(pdev, 0); 1603 - if (irq < 0) 1604 - return irq; 1605 - 1606 - ret = devm_request_threaded_irq(dev, irq, imx_hdmi_hardirq, 1607 - imx_hdmi_irq, IRQF_SHARED, 1608 - dev_name(dev), hdmi); 1609 - if (ret) 1610 - return ret; 1611 - 1612 - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1613 1629 hdmi->regs = devm_ioremap_resource(dev, iores); 1614 1630 if (IS_ERR(hdmi->regs)) 1615 1631 return PTR_ERR(hdmi->regs); 1616 1632 1617 - hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr"); 1618 - if (IS_ERR(hdmi->regmap)) 1619 - return PTR_ERR(hdmi->regmap); 1620 - 1621 1633 hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); 1622 1634 if (IS_ERR(hdmi->isfr_clk)) { 1623 1635 ret = PTR_ERR(hdmi->isfr_clk); 1624 - dev_err(hdmi->dev, 1625 - "Unable to get HDMI isfr clk: %d\n", ret); 1636 + dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret); 1626 1637 return ret; 1627 1638 } 1628 1639 1629 1640 ret = clk_prepare_enable(hdmi->isfr_clk); 1630 1641 if (ret) { 1631 - dev_err(hdmi->dev, 1632 - "Cannot enable HDMI isfr clock: %d\n", ret); 1642 + dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret); 1633 1643 return ret; 1634 1644 } 1635 1645 1636 1646 hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb"); 1637 1647 if (IS_ERR(hdmi->iahb_clk)) { 1638 1648 ret = PTR_ERR(hdmi->iahb_clk); 1639 - dev_err(hdmi->dev, 1640 - "Unable to get HDMI iahb clk: %d\n", ret); 1649 + dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret); 1641 1650 goto err_isfr; 1642 1651 } 1643 1652 1644 1653 ret = clk_prepare_enable(hdmi->iahb_clk); 1645 1654 if (ret) { 1646 - dev_err(hdmi->dev, 1647 - "Cannot enable HDMI iahb clock: %d\n", ret); 1655 + dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret); 1648 1656 goto err_isfr; 1649 1657 } 1650 1658 1651 1659 /* Product and revision IDs */ 1652 1660 dev_info(dev, 1653 - "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n", 1654 - hdmi_readb(hdmi, HDMI_DESIGN_ID), 1655 - hdmi_readb(hdmi, HDMI_REVISION_ID), 1656 - hdmi_readb(hdmi, HDMI_PRODUCT_ID0), 1657 - hdmi_readb(hdmi, HDMI_PRODUCT_ID1)); 1661 + "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n", 1662 + hdmi_readb(hdmi, HDMI_DESIGN_ID), 1663 + hdmi_readb(hdmi, HDMI_REVISION_ID), 1664 + hdmi_readb(hdmi, HDMI_PRODUCT_ID0), 1665 + hdmi_readb(hdmi, HDMI_PRODUCT_ID1)); 1658 1666 1659 1667 initialize_hdmi_ih_mutes(hdmi); 1668 + 1669 + ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq, 1670 + dw_hdmi_irq, IRQF_SHARED, 1671 + dev_name(dev), hdmi); 1672 + if (ret) 1673 + return ret; 1660 1674 1661 1675 /* 1662 1676 * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator ··· 1666 1694 /* Clear Hotplug interrupts */ 1667 1695 hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0); 1668 1696 1669 - ret = imx_hdmi_fb_registered(hdmi); 1697 + ret = dw_hdmi_fb_registered(hdmi); 1670 1698 if (ret) 1671 1699 goto err_iahb; 1672 1700 1673 - ret = imx_hdmi_register(drm, hdmi); 1701 + ret = dw_hdmi_register(drm, hdmi); 1674 1702 if (ret) 1675 1703 goto err_iahb; 1676 1704 ··· 1688 1716 1689 1717 return ret; 1690 1718 } 1719 + EXPORT_SYMBOL_GPL(dw_hdmi_bind); 1691 1720 1692 - static void imx_hdmi_unbind(struct device *dev, struct device *master, 1693 - void *data) 1721 + void dw_hdmi_unbind(struct device *dev, struct device *master, void *data) 1694 1722 { 1695 - struct imx_hdmi *hdmi = dev_get_drvdata(dev); 1723 + struct dw_hdmi *hdmi = dev_get_drvdata(dev); 1696 1724 1697 1725 /* Disable all interrupts */ 1698 1726 hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); 1699 1727 1700 1728 hdmi->connector.funcs->destroy(&hdmi->connector); 1701 - hdmi->encoder.funcs->destroy(&hdmi->encoder); 1729 + hdmi->encoder->funcs->destroy(hdmi->encoder); 1702 1730 1703 1731 clk_disable_unprepare(hdmi->iahb_clk); 1704 1732 clk_disable_unprepare(hdmi->isfr_clk); 1705 1733 i2c_put_adapter(hdmi->ddc); 1706 1734 } 1707 - 1708 - static const struct component_ops hdmi_ops = { 1709 - .bind = imx_hdmi_bind, 1710 - .unbind = imx_hdmi_unbind, 1711 - }; 1712 - 1713 - static int imx_hdmi_platform_probe(struct platform_device *pdev) 1714 - { 1715 - return component_add(&pdev->dev, &hdmi_ops); 1716 - } 1717 - 1718 - static int imx_hdmi_platform_remove(struct platform_device *pdev) 1719 - { 1720 - component_del(&pdev->dev, &hdmi_ops); 1721 - return 0; 1722 - } 1723 - 1724 - static struct platform_driver imx_hdmi_driver = { 1725 - .probe = imx_hdmi_platform_probe, 1726 - .remove = imx_hdmi_platform_remove, 1727 - .driver = { 1728 - .name = "imx-hdmi", 1729 - .of_match_table = imx_hdmi_dt_ids, 1730 - }, 1731 - }; 1732 - 1733 - module_platform_driver(imx_hdmi_driver); 1735 + EXPORT_SYMBOL_GPL(dw_hdmi_unbind); 1734 1736 1735 1737 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); 1736 - MODULE_DESCRIPTION("i.MX6 HDMI transmitter driver"); 1738 + MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>"); 1739 + MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); 1740 + MODULE_DESCRIPTION("DW HDMI transmitter driver"); 1737 1741 MODULE_LICENSE("GPL"); 1738 - MODULE_ALIAS("platform:imx-hdmi"); 1742 + MODULE_ALIAS("platform:dw-hdmi");
+3 -1
drivers/gpu/drm/imx/imx-hdmi.h drivers/gpu/drm/bridge/dw_hdmi.h
··· 837 837 HDMI_PHY_CONF0_PDZ_OFFSET = 7, 838 838 HDMI_PHY_CONF0_ENTMDS_MASK = 0x40, 839 839 HDMI_PHY_CONF0_ENTMDS_OFFSET = 6, 840 - HDMI_PHY_CONF0_SPARECTRL = 0x20, 840 + HDMI_PHY_CONF0_SPARECTRL_MASK = 0x20, 841 + HDMI_PHY_CONF0_SPARECTRL_OFFSET = 5, 841 842 HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10, 842 843 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4, 843 844 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8, ··· 1030 1029 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2, 1031 1030 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0, 1032 1031 }; 1032 + 1033 1033 #endif /* __IMX_HDMI_H__ */
+5 -3
drivers/gpu/drm/imx/imx-ldb.c
··· 163 163 { 164 164 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); 165 165 struct imx_ldb *ldb = imx_ldb_ch->ldb; 166 - struct drm_display_mode *mode = &encoder->crtc->mode; 166 + struct drm_display_mode *mode = &encoder->crtc->hwmode; 167 167 u32 pixel_fmt; 168 168 unsigned long serial_clk; 169 169 unsigned long di_clk = mode->clock * 1000; ··· 241 241 } 242 242 243 243 static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, 244 - struct drm_display_mode *mode, 245 - struct drm_display_mode *adjusted_mode) 244 + struct drm_display_mode *orig_mode, 245 + struct drm_display_mode *mode) 246 246 { 247 247 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); 248 248 struct imx_ldb *ldb = imx_ldb_ch->ldb; ··· 574 574 575 575 channel->connector.funcs->destroy(&channel->connector); 576 576 channel->encoder.funcs->destroy(&channel->encoder); 577 + 578 + kfree(channel->edid); 577 579 } 578 580 } 579 581
+2 -2
drivers/gpu/drm/imx/imx-tve.c
··· 307 307 } 308 308 309 309 static void imx_tve_encoder_mode_set(struct drm_encoder *encoder, 310 - struct drm_display_mode *mode, 311 - struct drm_display_mode *adjusted_mode) 310 + struct drm_display_mode *orig_mode, 311 + struct drm_display_mode *mode) 312 312 { 313 313 struct imx_tve *tve = enc_to_tve(encoder); 314 314 unsigned long rounded_rate;
+40 -38
drivers/gpu/drm/imx/ipuv3-crtc.c
··· 46 46 struct drm_framebuffer *newfb; 47 47 int irq; 48 48 u32 interface_pix_fmt; 49 - unsigned long di_clkflags; 50 49 int di_hsync_pin; 51 50 int di_vsync_pin; 52 51 }; ··· 140 141 int x, int y, 141 142 struct drm_framebuffer *old_fb) 142 143 { 144 + struct drm_device *dev = crtc->dev; 145 + struct drm_encoder *encoder; 143 146 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 144 - int ret; 145 147 struct ipu_di_signal_cfg sig_cfg = {}; 148 + unsigned long encoder_types = 0; 146 149 u32 out_pixel_fmt; 150 + int ret; 147 151 148 152 dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, 149 153 mode->hdisplay); 150 154 dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, 151 155 mode->vdisplay); 152 156 153 - out_pixel_fmt = ipu_crtc->interface_pix_fmt; 157 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 158 + if (encoder->crtc == crtc) 159 + encoder_types |= BIT(encoder->encoder_type); 154 160 155 - if (mode->flags & DRM_MODE_FLAG_INTERLACE) 156 - sig_cfg.interlaced = 1; 157 - if (mode->flags & DRM_MODE_FLAG_PHSYNC) 158 - sig_cfg.Hsync_pol = 1; 159 - if (mode->flags & DRM_MODE_FLAG_PVSYNC) 160 - sig_cfg.Vsync_pol = 1; 161 + dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n", 162 + __func__, encoder_types); 163 + 164 + /* 165 + * If we have DAC, TVDAC or LDB, then we need the IPU DI clock 166 + * to be the same as the LDB DI clock. 167 + */ 168 + if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) | 169 + BIT(DRM_MODE_ENCODER_TVDAC) | 170 + BIT(DRM_MODE_ENCODER_LVDS))) 171 + sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT; 172 + else 173 + sig_cfg.clkflags = 0; 174 + 175 + out_pixel_fmt = ipu_crtc->interface_pix_fmt; 161 176 162 177 sig_cfg.enable_pol = 1; 163 178 sig_cfg.clk_pol = 0; 164 - sig_cfg.width = mode->hdisplay; 165 - sig_cfg.height = mode->vdisplay; 166 179 sig_cfg.pixel_fmt = out_pixel_fmt; 167 - sig_cfg.h_start_width = mode->htotal - mode->hsync_end; 168 - sig_cfg.h_sync_width = mode->hsync_end - mode->hsync_start; 169 - sig_cfg.h_end_width = mode->hsync_start - mode->hdisplay; 170 - 171 - sig_cfg.v_start_width = mode->vtotal - mode->vsync_end; 172 - sig_cfg.v_sync_width = mode->vsync_end - mode->vsync_start; 173 - sig_cfg.v_end_width = mode->vsync_start - mode->vdisplay; 174 - sig_cfg.pixelclock = mode->clock * 1000; 175 - sig_cfg.clkflags = ipu_crtc->di_clkflags; 176 - 177 180 sig_cfg.v_to_h_sync = 0; 178 - 179 181 sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin; 180 182 sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin; 181 183 182 - ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, sig_cfg.interlaced, 183 - out_pixel_fmt, mode->hdisplay); 184 + drm_display_mode_to_videomode(mode, &sig_cfg.mode); 185 + 186 + ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, 187 + mode->flags & DRM_MODE_FLAG_INTERLACE, 188 + out_pixel_fmt, mode->hdisplay); 184 189 if (ret) { 185 190 dev_err(ipu_crtc->dev, 186 191 "initializing display controller failed with %d\n", ··· 240 237 const struct drm_display_mode *mode, 241 238 struct drm_display_mode *adjusted_mode) 242 239 { 240 + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 241 + struct videomode vm; 242 + int ret; 243 + 244 + drm_display_mode_to_videomode(adjusted_mode, &vm); 245 + 246 + ret = ipu_di_adjust_videomode(ipu_crtc->di, &vm); 247 + if (ret) 248 + return false; 249 + 250 + drm_display_mode_from_videomode(&vm, adjusted_mode); 251 + 243 252 return true; 244 253 } 245 254 ··· 290 275 ipu_crtc->newfb = NULL; 291 276 } 292 277 293 - static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type, 278 + static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, 294 279 u32 pixfmt, int hsync_pin, int vsync_pin) 295 280 { 296 281 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); ··· 298 283 ipu_crtc->interface_pix_fmt = pixfmt; 299 284 ipu_crtc->di_hsync_pin = hsync_pin; 300 285 ipu_crtc->di_vsync_pin = vsync_pin; 301 - 302 - switch (encoder_type) { 303 - case DRM_MODE_ENCODER_DAC: 304 - case DRM_MODE_ENCODER_TVDAC: 305 - case DRM_MODE_ENCODER_LVDS: 306 - ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC | 307 - IPU_DI_CLKMODE_EXT; 308 - break; 309 - case DRM_MODE_ENCODER_TMDS: 310 - case DRM_MODE_ENCODER_NONE: 311 - ipu_crtc->di_clkflags = 0; 312 - break; 313 - } 314 286 315 287 return 0; 316 288 }
+5 -2
drivers/gpu/drm/imx/parallel-display.c
··· 130 130 } 131 131 132 132 static void imx_pd_encoder_mode_set(struct drm_encoder *encoder, 133 - struct drm_display_mode *mode, 134 - struct drm_display_mode *adjusted_mode) 133 + struct drm_display_mode *orig_mode, 134 + struct drm_display_mode *mode) 135 135 { 136 136 } 137 137 ··· 257 257 258 258 imxpd->encoder.funcs->destroy(&imxpd->encoder); 259 259 imxpd->connector.funcs->destroy(&imxpd->connector); 260 + 261 + kfree(imxpd->edid); 260 262 } 261 263 262 264 static const struct component_ops imx_pd_ops = { ··· 274 272 static int imx_pd_remove(struct platform_device *pdev) 275 273 { 276 274 component_del(&pdev->dev, &imx_pd_ops); 275 + 277 276 return 0; 278 277 } 279 278
+10
drivers/gpu/drm/rockchip/Kconfig
··· 15 15 management to userspace. This driver does not provide 16 16 2D or 3D acceleration; acceleration is performed by other 17 17 IP found on the SoC. 18 + 19 + config ROCKCHIP_DW_HDMI 20 + tristate "Rockchip specific extensions for Synopsys DW HDMI" 21 + depends on DRM_ROCKCHIP 22 + select DRM_DW_HDMI 23 + help 24 + This selects support for Rockchip SoC specific extensions 25 + for the Synopsys DesignWare HDMI driver. If you want to 26 + enable HDMI on RK3288 based SoC, you should selet this 27 + option.
+2
drivers/gpu/drm/rockchip/Makefile
··· 5 5 rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o rockchip_drm_fbdev.o \ 6 6 rockchip_drm_gem.o 7 7 8 + obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o 9 + 8 10 obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o
+341
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
··· 1 + /* 2 + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License as published by 6 + * the Free Software Foundation; either version 2 of the License, or 7 + * (at your option) any later version. 8 + */ 9 + 10 + #include <linux/module.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/mfd/syscon.h> 13 + #include <linux/regmap.h> 14 + #include <drm/drm_of.h> 15 + #include <drm/drmP.h> 16 + #include <drm/drm_crtc_helper.h> 17 + #include <drm/drm_edid.h> 18 + #include <drm/drm_encoder_slave.h> 19 + #include <drm/bridge/dw_hdmi.h> 20 + 21 + #include "rockchip_drm_drv.h" 22 + #include "rockchip_drm_vop.h" 23 + 24 + #define GRF_SOC_CON6 0x025c 25 + #define HDMI_SEL_VOP_LIT (1 << 4) 26 + 27 + struct rockchip_hdmi { 28 + struct device *dev; 29 + struct regmap *regmap; 30 + struct drm_encoder encoder; 31 + }; 32 + 33 + #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) 34 + 35 + static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { 36 + { 37 + 27000000, { 38 + { 0x00b3, 0x0000}, 39 + { 0x2153, 0x0000}, 40 + { 0x40f3, 0x0000} 41 + }, 42 + }, { 43 + 36000000, { 44 + { 0x00b3, 0x0000}, 45 + { 0x2153, 0x0000}, 46 + { 0x40f3, 0x0000} 47 + }, 48 + }, { 49 + 40000000, { 50 + { 0x00b3, 0x0000}, 51 + { 0x2153, 0x0000}, 52 + { 0x40f3, 0x0000} 53 + }, 54 + }, { 55 + 54000000, { 56 + { 0x0072, 0x0001}, 57 + { 0x2142, 0x0001}, 58 + { 0x40a2, 0x0001}, 59 + }, 60 + }, { 61 + 65000000, { 62 + { 0x0072, 0x0001}, 63 + { 0x2142, 0x0001}, 64 + { 0x40a2, 0x0001}, 65 + }, 66 + }, { 67 + 66000000, { 68 + { 0x013e, 0x0003}, 69 + { 0x217e, 0x0002}, 70 + { 0x4061, 0x0002} 71 + }, 72 + }, { 73 + 74250000, { 74 + { 0x0072, 0x0001}, 75 + { 0x2145, 0x0002}, 76 + { 0x4061, 0x0002} 77 + }, 78 + }, { 79 + 83500000, { 80 + { 0x0072, 0x0001}, 81 + }, 82 + }, { 83 + 108000000, { 84 + { 0x0051, 0x0002}, 85 + { 0x2145, 0x0002}, 86 + { 0x4061, 0x0002} 87 + }, 88 + }, { 89 + 106500000, { 90 + { 0x0051, 0x0002}, 91 + { 0x2145, 0x0002}, 92 + { 0x4061, 0x0002} 93 + }, 94 + }, { 95 + 146250000, { 96 + { 0x0051, 0x0002}, 97 + { 0x2145, 0x0002}, 98 + { 0x4061, 0x0002} 99 + }, 100 + }, { 101 + 148500000, { 102 + { 0x0051, 0x0003}, 103 + { 0x214c, 0x0003}, 104 + { 0x4064, 0x0003} 105 + }, 106 + }, { 107 + ~0UL, { 108 + { 0x00a0, 0x000a }, 109 + { 0x2001, 0x000f }, 110 + { 0x4002, 0x000f }, 111 + }, 112 + } 113 + }; 114 + 115 + static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { 116 + /* pixelclk bpp8 bpp10 bpp12 */ 117 + { 118 + 40000000, { 0x0018, 0x0018, 0x0018 }, 119 + }, { 120 + 65000000, { 0x0028, 0x0028, 0x0028 }, 121 + }, { 122 + 66000000, { 0x0038, 0x0038, 0x0038 }, 123 + }, { 124 + 74250000, { 0x0028, 0x0038, 0x0038 }, 125 + }, { 126 + 83500000, { 0x0028, 0x0038, 0x0038 }, 127 + }, { 128 + 146250000, { 0x0038, 0x0038, 0x0038 }, 129 + }, { 130 + 148500000, { 0x0000, 0x0038, 0x0038 }, 131 + }, { 132 + ~0UL, { 0x0000, 0x0000, 0x0000}, 133 + } 134 + }; 135 + 136 + static const struct dw_hdmi_sym_term rockchip_sym_term[] = { 137 + /*pixelclk symbol term*/ 138 + { 74250000, 0x8009, 0x0004 }, 139 + { 148500000, 0x8029, 0x0004 }, 140 + { 297000000, 0x8039, 0x0005 }, 141 + { ~0UL, 0x0000, 0x0000 } 142 + }; 143 + 144 + static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) 145 + { 146 + struct device_node *np = hdmi->dev->of_node; 147 + 148 + hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 149 + if (IS_ERR(hdmi->regmap)) { 150 + dev_err(hdmi->dev, "Unable to get rockchip,grf\n"); 151 + return PTR_ERR(hdmi->regmap); 152 + } 153 + 154 + return 0; 155 + } 156 + 157 + static enum drm_mode_status 158 + dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, 159 + struct drm_display_mode *mode) 160 + { 161 + const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; 162 + int pclk = mode->clock * 1000; 163 + bool valid = false; 164 + int i; 165 + 166 + for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { 167 + if (pclk == mpll_cfg[i].mpixelclock) { 168 + valid = true; 169 + break; 170 + } 171 + } 172 + 173 + return (valid) ? MODE_OK : MODE_BAD; 174 + } 175 + 176 + static struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = { 177 + .destroy = drm_encoder_cleanup, 178 + }; 179 + 180 + static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) 181 + { 182 + } 183 + 184 + static bool 185 + dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, 186 + const struct drm_display_mode *mode, 187 + struct drm_display_mode *adj_mode) 188 + { 189 + return true; 190 + } 191 + 192 + static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, 193 + struct drm_display_mode *mode, 194 + struct drm_display_mode *adj_mode) 195 + { 196 + } 197 + 198 + static void dw_hdmi_rockchip_encoder_commit(struct drm_encoder *encoder) 199 + { 200 + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); 201 + u32 val; 202 + int mux; 203 + 204 + mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder); 205 + if (mux) 206 + val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16); 207 + else 208 + val = HDMI_SEL_VOP_LIT << 16; 209 + 210 + regmap_write(hdmi->regmap, GRF_SOC_CON6, val); 211 + dev_dbg(hdmi->dev, "vop %s output to hdmi\n", 212 + (mux) ? "LIT" : "BIG"); 213 + } 214 + 215 + static void dw_hdmi_rockchip_encoder_prepare(struct drm_encoder *encoder) 216 + { 217 + rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA, 218 + ROCKCHIP_OUT_MODE_AAAA); 219 + } 220 + 221 + static struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { 222 + .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, 223 + .mode_set = dw_hdmi_rockchip_encoder_mode_set, 224 + .prepare = dw_hdmi_rockchip_encoder_prepare, 225 + .commit = dw_hdmi_rockchip_encoder_commit, 226 + .disable = dw_hdmi_rockchip_encoder_disable, 227 + }; 228 + 229 + static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = { 230 + .mode_valid = dw_hdmi_rockchip_mode_valid, 231 + .mpll_cfg = rockchip_mpll_cfg, 232 + .cur_ctr = rockchip_cur_ctr, 233 + .sym_term = rockchip_sym_term, 234 + .dev_type = RK3288_HDMI, 235 + }; 236 + 237 + static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { 238 + { .compatible = "rockchip,rk3288-dw-hdmi", 239 + .data = &rockchip_hdmi_drv_data 240 + }, 241 + {}, 242 + }; 243 + MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids); 244 + 245 + static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, 246 + void *data) 247 + { 248 + struct platform_device *pdev = to_platform_device(dev); 249 + const struct dw_hdmi_plat_data *plat_data; 250 + const struct of_device_id *match; 251 + struct drm_device *drm = data; 252 + struct drm_encoder *encoder; 253 + struct rockchip_hdmi *hdmi; 254 + struct resource *iores; 255 + int irq; 256 + int ret; 257 + 258 + if (!pdev->dev.of_node) 259 + return -ENODEV; 260 + 261 + hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); 262 + if (!hdmi) 263 + return -ENOMEM; 264 + 265 + match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); 266 + plat_data = match->data; 267 + hdmi->dev = &pdev->dev; 268 + encoder = &hdmi->encoder; 269 + 270 + irq = platform_get_irq(pdev, 0); 271 + if (irq < 0) 272 + return irq; 273 + 274 + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 275 + if (!iores) 276 + return -ENXIO; 277 + 278 + platform_set_drvdata(pdev, hdmi); 279 + 280 + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); 281 + /* 282 + * If we failed to find the CRTC(s) which this encoder is 283 + * supposed to be connected to, it's because the CRTC has 284 + * not been registered yet. Defer probing, and hope that 285 + * the required CRTC is added later. 286 + */ 287 + if (encoder->possible_crtcs == 0) 288 + return -EPROBE_DEFER; 289 + 290 + ret = rockchip_hdmi_parse_dt(hdmi); 291 + if (ret) { 292 + dev_err(hdmi->dev, "Unable to parse OF data\n"); 293 + return ret; 294 + } 295 + 296 + drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); 297 + drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, 298 + DRM_MODE_ENCODER_TMDS); 299 + 300 + return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data); 301 + } 302 + 303 + static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, 304 + void *data) 305 + { 306 + return dw_hdmi_unbind(dev, master, data); 307 + } 308 + 309 + static const struct component_ops dw_hdmi_rockchip_ops = { 310 + .bind = dw_hdmi_rockchip_bind, 311 + .unbind = dw_hdmi_rockchip_unbind, 312 + }; 313 + 314 + static int dw_hdmi_rockchip_probe(struct platform_device *pdev) 315 + { 316 + return component_add(&pdev->dev, &dw_hdmi_rockchip_ops); 317 + } 318 + 319 + static int dw_hdmi_rockchip_remove(struct platform_device *pdev) 320 + { 321 + component_del(&pdev->dev, &dw_hdmi_rockchip_ops); 322 + 323 + return 0; 324 + } 325 + 326 + static struct platform_driver dw_hdmi_rockchip_pltfm_driver = { 327 + .probe = dw_hdmi_rockchip_probe, 328 + .remove = dw_hdmi_rockchip_remove, 329 + .driver = { 330 + .name = "dwhdmi-rockchip", 331 + .of_match_table = dw_hdmi_rockchip_dt_ids, 332 + }, 333 + }; 334 + 335 + module_platform_driver(dw_hdmi_rockchip_pltfm_driver); 336 + 337 + MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>"); 338 + MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); 339 + MODULE_DESCRIPTION("Rockchip Specific DW-HDMI Driver Extension"); 340 + MODULE_LICENSE("GPL"); 341 + MODULE_ALIAS("platform:dwhdmi-rockchip");
+1
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
··· 390 390 391 391 return -EINVAL; 392 392 } 393 + EXPORT_SYMBOL_GPL(rockchip_drm_encoder_get_mux_id); 393 394 394 395 static int compare_of(struct device *dev, void *data) 395 396 {
+1
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
··· 735 735 736 736 return 0; 737 737 } 738 + EXPORT_SYMBOL_GPL(rockchip_drm_crtc_mode_config); 738 739 739 740 static int vop_crtc_enable_vblank(struct drm_crtc *crtc) 740 741 {
+23 -2
drivers/gpu/ipu-v3/ipu-dc.c
··· 114 114 struct completion comp; 115 115 int dc_irq; 116 116 int dp_irq; 117 + int use_count; 117 118 }; 118 119 119 120 static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority) ··· 233 232 234 233 void ipu_dc_enable(struct ipu_soc *ipu) 235 234 { 236 - ipu_module_enable(ipu, IPU_CONF_DC_EN); 235 + struct ipu_dc_priv *priv = ipu->dc_priv; 236 + 237 + mutex_lock(&priv->mutex); 238 + 239 + if (!priv->use_count) 240 + ipu_module_enable(priv->ipu, IPU_CONF_DC_EN); 241 + 242 + priv->use_count++; 243 + 244 + mutex_unlock(&priv->mutex); 237 245 } 238 246 EXPORT_SYMBOL_GPL(ipu_dc_enable); 239 247 ··· 304 294 305 295 void ipu_dc_disable(struct ipu_soc *ipu) 306 296 { 307 - ipu_module_disable(ipu, IPU_CONF_DC_EN); 297 + struct ipu_dc_priv *priv = ipu->dc_priv; 298 + 299 + mutex_lock(&priv->mutex); 300 + 301 + priv->use_count--; 302 + if (!priv->use_count) 303 + ipu_module_disable(priv->ipu, IPU_CONF_DC_EN); 304 + 305 + if (priv->use_count < 0) 306 + priv->use_count = 0; 307 + 308 + mutex_unlock(&priv->mutex); 308 309 } 309 310 EXPORT_SYMBOL_GPL(ipu_dc_disable); 310 311
+74 -47
drivers/gpu/ipu-v3/ipu-di.c
··· 207 207 static void ipu_di_sync_config_interlaced(struct ipu_di *di, 208 208 struct ipu_di_signal_cfg *sig) 209 209 { 210 - u32 h_total = sig->width + sig->h_sync_width + 211 - sig->h_start_width + sig->h_end_width; 212 - u32 v_total = sig->height + sig->v_sync_width + 213 - sig->v_start_width + sig->v_end_width; 210 + u32 h_total = sig->mode.hactive + sig->mode.hsync_len + 211 + sig->mode.hback_porch + sig->mode.hfront_porch; 212 + u32 v_total = sig->mode.vactive + sig->mode.vsync_len + 213 + sig->mode.vback_porch + sig->mode.vfront_porch; 214 214 u32 reg; 215 215 struct di_sync_config cfg[] = { 216 216 { ··· 229 229 }, { 230 230 .run_count = v_total / 2 - 1, 231 231 .run_src = DI_SYNC_HSYNC, 232 - .offset_count = sig->v_start_width, 232 + .offset_count = sig->mode.vback_porch, 233 233 .offset_src = DI_SYNC_HSYNC, 234 234 .repeat_count = 2, 235 235 .cnt_clr_src = DI_SYNC_VSYNC, 236 236 }, { 237 237 .run_src = DI_SYNC_HSYNC, 238 - .repeat_count = sig->height / 2, 238 + .repeat_count = sig->mode.vactive / 2, 239 239 .cnt_clr_src = 4, 240 240 }, { 241 241 .run_count = v_total - 1, ··· 249 249 .cnt_clr_src = DI_SYNC_VSYNC, 250 250 }, { 251 251 .run_src = DI_SYNC_CLK, 252 - .offset_count = sig->h_start_width, 252 + .offset_count = sig->mode.hback_porch, 253 253 .offset_src = DI_SYNC_CLK, 254 - .repeat_count = sig->width, 254 + .repeat_count = sig->mode.hactive, 255 255 .cnt_clr_src = 5, 256 256 }, { 257 257 .run_count = v_total - 1, ··· 277 277 static void ipu_di_sync_config_noninterlaced(struct ipu_di *di, 278 278 struct ipu_di_signal_cfg *sig, int div) 279 279 { 280 - u32 h_total = sig->width + sig->h_sync_width + sig->h_start_width + 281 - sig->h_end_width; 282 - u32 v_total = sig->height + sig->v_sync_width + sig->v_start_width + 283 - sig->v_end_width; 280 + u32 h_total = sig->mode.hactive + sig->mode.hsync_len + 281 + sig->mode.hback_porch + sig->mode.hfront_porch; 282 + u32 v_total = sig->mode.vactive + sig->mode.vsync_len + 283 + sig->mode.vback_porch + sig->mode.vfront_porch; 284 284 struct di_sync_config cfg[] = { 285 285 { 286 286 /* 1: INT_HSYNC */ ··· 294 294 .offset_src = DI_SYNC_CLK, 295 295 .cnt_polarity_gen_en = 1, 296 296 .cnt_polarity_trigger_src = DI_SYNC_CLK, 297 - .cnt_down = sig->h_sync_width * 2, 297 + .cnt_down = sig->mode.hsync_len * 2, 298 298 } , { 299 299 /* PIN3: VSYNC */ 300 300 .run_count = v_total - 1, 301 301 .run_src = DI_SYNC_INT_HSYNC, 302 302 .cnt_polarity_gen_en = 1, 303 303 .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC, 304 - .cnt_down = sig->v_sync_width * 2, 304 + .cnt_down = sig->mode.vsync_len * 2, 305 305 } , { 306 306 /* 4: Line Active */ 307 307 .run_src = DI_SYNC_HSYNC, 308 - .offset_count = sig->v_sync_width + sig->v_start_width, 308 + .offset_count = sig->mode.vsync_len + 309 + sig->mode.vback_porch, 309 310 .offset_src = DI_SYNC_HSYNC, 310 - .repeat_count = sig->height, 311 + .repeat_count = sig->mode.vactive, 311 312 .cnt_clr_src = DI_SYNC_VSYNC, 312 313 } , { 313 314 /* 5: Pixel Active, referenced by DC */ 314 315 .run_src = DI_SYNC_CLK, 315 - .offset_count = sig->h_sync_width + sig->h_start_width, 316 + .offset_count = sig->mode.hsync_len + 317 + sig->mode.hback_porch, 316 318 .offset_src = DI_SYNC_CLK, 317 - .repeat_count = sig->width, 319 + .repeat_count = sig->mode.hactive, 318 320 .cnt_clr_src = 5, /* Line Active */ 319 321 } , { 320 322 /* unused */ ··· 341 339 } , { 342 340 /* 3: Line Active */ 343 341 .run_src = DI_SYNC_INT_HSYNC, 344 - .offset_count = sig->v_sync_width + sig->v_start_width, 342 + .offset_count = sig->mode.vsync_len + 343 + sig->mode.vback_porch, 345 344 .offset_src = DI_SYNC_INT_HSYNC, 346 - .repeat_count = sig->height, 345 + .repeat_count = sig->mode.vactive, 347 346 .cnt_clr_src = 3 /* VSYNC */, 348 347 } , { 349 348 /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */ ··· 354 351 .offset_src = DI_SYNC_CLK, 355 352 .cnt_polarity_gen_en = 1, 356 353 .cnt_polarity_trigger_src = DI_SYNC_CLK, 357 - .cnt_down = sig->h_sync_width * 2, 354 + .cnt_down = sig->mode.hsync_len * 2, 358 355 } , { 359 356 /* 5: Pixel Active signal to DC */ 360 357 .run_src = DI_SYNC_CLK, 361 - .offset_count = sig->h_sync_width + sig->h_start_width, 358 + .offset_count = sig->mode.hsync_len + 359 + sig->mode.hback_porch, 362 360 .offset_src = DI_SYNC_CLK, 363 - .repeat_count = sig->width, 361 + .repeat_count = sig->mode.hactive, 364 362 .cnt_clr_src = 4, /* Line Active */ 365 363 } , { 366 364 /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */ ··· 371 367 .offset_src = DI_SYNC_INT_HSYNC, 372 368 .cnt_polarity_gen_en = 1, 373 369 .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC, 374 - .cnt_down = sig->v_sync_width * 2, 370 + .cnt_down = sig->mode.vsync_len * 2, 375 371 } , { 376 372 /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */ 377 373 .run_count = h_total - 1, ··· 380 376 .offset_src = DI_SYNC_CLK, 381 377 .cnt_polarity_gen_en = 1, 382 378 .cnt_polarity_trigger_src = DI_SYNC_CLK, 383 - .cnt_down = sig->h_sync_width * 2, 379 + .cnt_down = sig->mode.hsync_len * 2, 384 380 } , { 385 381 /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */ 386 382 .run_count = v_total - 1, ··· 389 385 .offset_src = DI_SYNC_INT_HSYNC, 390 386 .cnt_polarity_gen_en = 1, 391 387 .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC, 392 - .cnt_down = sig->v_sync_width * 2, 388 + .cnt_down = sig->mode.vsync_len * 2, 393 389 } , { 394 390 /* unused */ 395 391 }, ··· 437 433 unsigned long in_rate; 438 434 unsigned div; 439 435 440 - clk_set_rate(clk, sig->pixelclock); 436 + clk_set_rate(clk, sig->mode.pixelclock); 441 437 442 438 in_rate = clk_get_rate(clk); 443 - div = (in_rate + sig->pixelclock / 2) / sig->pixelclock; 439 + div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock); 444 440 if (div == 0) 445 441 div = 1; 446 442 ··· 458 454 unsigned div, error; 459 455 460 456 clkrate = clk_get_rate(di->clk_ipu); 461 - div = (clkrate + sig->pixelclock / 2) / sig->pixelclock; 457 + div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock); 462 458 rate = clkrate / div; 463 459 464 - error = rate / (sig->pixelclock / 1000); 460 + error = rate / (sig->mode.pixelclock / 1000); 465 461 466 462 dev_dbg(di->ipu->dev, " IPU clock can give %lu with divider %u, error %d.%u%%\n", 467 463 rate, div, (signed)(error - 1000) / 10, error % 10); ··· 477 473 478 474 clk = di->clk_di; 479 475 480 - clk_set_rate(clk, sig->pixelclock); 476 + clk_set_rate(clk, sig->mode.pixelclock); 481 477 482 478 in_rate = clk_get_rate(clk); 483 - div = (in_rate + sig->pixelclock / 2) / sig->pixelclock; 479 + div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock); 484 480 if (div == 0) 485 481 div = 1; 486 482 ··· 508 504 ipu_di_write(di, val, DI_GENERAL); 509 505 510 506 dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n", 511 - sig->pixelclock, 507 + sig->mode.pixelclock, 512 508 clk_get_rate(di->clk_ipu), 513 509 clk_get_rate(di->clk_di), 514 510 clk == di->clk_di ? "DI" : "IPU", 515 511 clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4)); 516 512 } 517 513 514 + /* 515 + * This function is called to adjust a video mode to IPU restrictions. 516 + * It is meant to be called from drm crtc mode_fixup() methods. 517 + */ 518 + int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode) 519 + { 520 + u32 diff; 521 + 522 + if (mode->vfront_porch >= 2) 523 + return 0; 524 + 525 + diff = 2 - mode->vfront_porch; 526 + 527 + if (mode->vback_porch >= diff) { 528 + mode->vfront_porch = 2; 529 + mode->vback_porch -= diff; 530 + } else if (mode->vsync_len > diff) { 531 + mode->vfront_porch = 2; 532 + mode->vsync_len = mode->vsync_len - diff; 533 + } else { 534 + dev_warn(di->ipu->dev, "failed to adjust videomode\n"); 535 + return -EINVAL; 536 + } 537 + 538 + dev_warn(di->ipu->dev, "videomode adapted for IPU restrictions\n"); 539 + return 0; 540 + } 541 + EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode); 542 + 518 543 int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig) 519 544 { 520 545 u32 reg; 521 546 u32 di_gen, vsync_cnt; 522 547 u32 div; 523 - u32 h_total, v_total; 524 548 525 549 dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n", 526 - di->id, sig->width, sig->height); 550 + di->id, sig->mode.hactive, sig->mode.vactive); 527 551 528 - if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0)) 552 + if ((sig->mode.vsync_len == 0) || (sig->mode.hsync_len == 0)) 529 553 return -EINVAL; 530 - 531 - h_total = sig->width + sig->h_sync_width + sig->h_start_width + 532 - sig->h_end_width; 533 - v_total = sig->height + sig->v_sync_width + sig->v_start_width + 534 - sig->v_end_width; 535 554 536 555 dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n", 537 556 clk_get_rate(di->clk_ipu), 538 557 clk_get_rate(di->clk_di), 539 - sig->pixelclock); 558 + sig->mode.pixelclock); 540 559 541 560 mutex_lock(&di_mutex); 542 561 ··· 578 551 di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT; 579 552 di_gen |= DI_GEN_DI_VSYNC_EXT; 580 553 581 - if (sig->interlaced) { 554 + if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) { 582 555 ipu_di_sync_config_interlaced(di, sig); 583 556 584 557 /* set y_sel = 1 */ ··· 588 561 589 562 vsync_cnt = 7; 590 563 591 - if (sig->Hsync_pol) 564 + if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH) 592 565 di_gen |= DI_GEN_POLARITY_3; 593 - if (sig->Vsync_pol) 566 + if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH) 594 567 di_gen |= DI_GEN_POLARITY_2; 595 568 } else { 596 569 ipu_di_sync_config_noninterlaced(di, sig, div); ··· 604 577 if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3)) 605 578 vsync_cnt = 6; 606 579 607 - if (sig->Hsync_pol) { 580 + if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH) { 608 581 if (sig->hsync_pin == 2) 609 582 di_gen |= DI_GEN_POLARITY_2; 610 583 else if (sig->hsync_pin == 4) ··· 612 585 else if (sig->hsync_pin == 7) 613 586 di_gen |= DI_GEN_POLARITY_7; 614 587 } 615 - if (sig->Vsync_pol) { 588 + if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH) { 616 589 if (sig->vsync_pin == 3) 617 590 di_gen |= DI_GEN_POLARITY_3; 618 591 else if (sig->vsync_pin == 6)
+61
include/drm/bridge/dw_hdmi.h
··· 1 + /* 2 + * Copyright (C) 2011 Freescale Semiconductor, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License as published by 6 + * the Free Software Foundation; either version 2 of the License, or 7 + * (at your option) any later version. 8 + */ 9 + 10 + #ifndef __DW_HDMI__ 11 + #define __DW_HDMI__ 12 + 13 + #include <drm/drmP.h> 14 + 15 + enum { 16 + DW_HDMI_RES_8, 17 + DW_HDMI_RES_10, 18 + DW_HDMI_RES_12, 19 + DW_HDMI_RES_MAX, 20 + }; 21 + 22 + enum dw_hdmi_devtype { 23 + IMX6Q_HDMI, 24 + IMX6DL_HDMI, 25 + RK3288_HDMI, 26 + }; 27 + 28 + struct dw_hdmi_mpll_config { 29 + unsigned long mpixelclock; 30 + struct { 31 + u16 cpce; 32 + u16 gmp; 33 + } res[DW_HDMI_RES_MAX]; 34 + }; 35 + 36 + struct dw_hdmi_curr_ctrl { 37 + unsigned long mpixelclock; 38 + u16 curr[DW_HDMI_RES_MAX]; 39 + }; 40 + 41 + struct dw_hdmi_sym_term { 42 + unsigned long mpixelclock; 43 + u16 sym_ctr; /*clock symbol and transmitter control*/ 44 + u16 term; /*transmission termination value*/ 45 + }; 46 + 47 + struct dw_hdmi_plat_data { 48 + enum dw_hdmi_devtype dev_type; 49 + const struct dw_hdmi_mpll_config *mpll_cfg; 50 + const struct dw_hdmi_curr_ctrl *cur_ctr; 51 + const struct dw_hdmi_sym_term *sym_term; 52 + enum drm_mode_status (*mode_valid)(struct drm_connector *connector, 53 + struct drm_display_mode *mode); 54 + }; 55 + 56 + void dw_hdmi_unbind(struct device *dev, struct device *master, void *data); 57 + int dw_hdmi_bind(struct device *dev, struct device *master, 58 + void *data, struct drm_encoder *encoder, 59 + struct resource *iores, int irq, 60 + const struct dw_hdmi_plat_data *plat_data); 61 + #endif /* __IMX_HDMI_H__ */
+2
include/drm/drm_modes.h
··· 200 200 int GTF_K, int GTF_2J); 201 201 void drm_display_mode_from_videomode(const struct videomode *vm, 202 202 struct drm_display_mode *dmode); 203 + void drm_display_mode_to_videomode(const struct drm_display_mode *dmode, 204 + struct videomode *vm); 203 205 int of_get_drm_display_mode(struct device_node *np, 204 206 struct drm_display_mode *dmode, 205 207 int index);
+5 -16
include/video/imx-ipu-v3.h
··· 17 17 #include <linux/bitmap.h> 18 18 #include <linux/fb.h> 19 19 #include <media/v4l2-mediabus.h> 20 + #include <video/videomode.h> 20 21 21 22 struct ipu_soc; 22 23 ··· 33 32 * Bitfield of Display Interface signal polarities. 34 33 */ 35 34 struct ipu_di_signal_cfg { 36 - unsigned datamask_en:1; 37 - unsigned interlaced:1; 38 - unsigned odd_field_first:1; 39 - unsigned clksel_en:1; 40 - unsigned clkidle_en:1; 41 35 unsigned data_pol:1; /* true = inverted */ 42 36 unsigned clk_pol:1; /* true = rising edge */ 43 37 unsigned enable_pol:1; 44 - unsigned Hsync_pol:1; /* true = active high */ 45 - unsigned Vsync_pol:1; 46 38 47 - u16 width; 48 - u16 height; 39 + struct videomode mode; 40 + 49 41 u32 pixel_fmt; 50 - u16 h_start_width; 51 - u16 h_sync_width; 52 - u16 h_end_width; 53 - u16 v_start_width; 54 - u16 v_sync_width; 55 - u16 v_end_width; 56 42 u32 v_to_h_sync; 57 - unsigned long pixelclock; 43 + 58 44 #define IPU_DI_CLKMODE_SYNC (1 << 0) 59 45 #define IPU_DI_CLKMODE_EXT (1 << 1) 60 46 unsigned long clkflags; ··· 224 236 int ipu_di_disable(struct ipu_di *); 225 237 int ipu_di_enable(struct ipu_di *); 226 238 int ipu_di_get_num(struct ipu_di *); 239 + int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode); 227 240 int ipu_di_init_sync_panel(struct ipu_di *, struct ipu_di_signal_cfg *sig); 228 241 229 242 /*