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

drm: rcar-du: Add Gen3 HDMI encoder support

The R-Car Gen3 SoCs include on-chip DesignWare HDMI encoders. Support
them with a platform driver to provide platform glue data to the dw-hdmi
driver.

The driver is a complete rewrite of code coming from the Renesas BSP,
save for the values in the PHY parameters table.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

authored by

Koji Matsuoka and committed by
Laurent Pinchart
40d0fa70 907c1bbd

+108
+7
drivers/gpu/drm/rcar-du/Kconfig
··· 11 11 Choose this option if you have an R-Car chipset. 12 12 If M is selected the module will be called rcar-du-drm. 13 13 14 + config DRM_RCAR_DW_HDMI 15 + tristate "R-Car DU Gen3 HDMI Encoder Support" 16 + depends on DRM && OF 17 + select DRM_DW_HDMI 18 + help 19 + Enable support for R-Car Gen3 internal HDMI encoder. 20 + 14 21 config DRM_RCAR_LVDS 15 22 bool "R-Car DU LVDS Encoder Support" 16 23 depends on DRM_RCAR_DU
+1
drivers/gpu/drm/rcar-du/Makefile
··· 11 11 rcar-du-drm-$(CONFIG_DRM_RCAR_VSP) += rcar_du_vsp.o 12 12 13 13 obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o 14 + obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o
+100
drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
··· 1 + /* 2 + * R-Car Gen3 HDMI PHY 3 + * 4 + * Copyright (C) 2016 Renesas Electronics Corporation 5 + * 6 + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + */ 13 + 14 + #include <linux/module.h> 15 + #include <linux/platform_device.h> 16 + 17 + #include <drm/bridge/dw_hdmi.h> 18 + 19 + #define RCAR_HDMI_PHY_OPMODE_PLLCFG 0x06 /* Mode of operation and PLL dividers */ 20 + #define RCAR_HDMI_PHY_PLLCURRGMPCTRL 0x10 /* PLL current and Gmp (conductance) */ 21 + #define RCAR_HDMI_PHY_PLLDIVCTRL 0x11 /* PLL dividers */ 22 + 23 + struct rcar_hdmi_phy_params { 24 + unsigned long mpixelclock; 25 + u16 opmode_div; /* Mode of operation and PLL dividers */ 26 + u16 curr_gmp; /* PLL current and Gmp (conductance) */ 27 + u16 div; /* PLL dividers */ 28 + }; 29 + 30 + static const struct rcar_hdmi_phy_params rcar_hdmi_phy_params[] = { 31 + { 35500000, 0x0003, 0x0344, 0x0328 }, 32 + { 44900000, 0x0003, 0x0285, 0x0128 }, 33 + { 71000000, 0x0002, 0x1184, 0x0314 }, 34 + { 90000000, 0x0002, 0x1144, 0x0114 }, 35 + { 140250000, 0x0001, 0x20c4, 0x030a }, 36 + { 182750000, 0x0001, 0x2084, 0x010a }, 37 + { 281250000, 0x0000, 0x0084, 0x0305 }, 38 + { 297000000, 0x0000, 0x0084, 0x0105 }, 39 + { ~0UL, 0x0000, 0x0000, 0x0000 }, 40 + }; 41 + 42 + static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, 43 + const struct dw_hdmi_plat_data *pdata, 44 + unsigned long mpixelclock) 45 + { 46 + const struct rcar_hdmi_phy_params *params = rcar_hdmi_phy_params; 47 + 48 + for (; params && params->mpixelclock != ~0UL; ++params) { 49 + if (mpixelclock <= params->mpixelclock) 50 + break; 51 + } 52 + 53 + if (params->mpixelclock == ~0UL) 54 + return -EINVAL; 55 + 56 + dw_hdmi_phy_i2c_write(hdmi, params->opmode_div, 57 + RCAR_HDMI_PHY_OPMODE_PLLCFG); 58 + dw_hdmi_phy_i2c_write(hdmi, params->curr_gmp, 59 + RCAR_HDMI_PHY_PLLCURRGMPCTRL); 60 + dw_hdmi_phy_i2c_write(hdmi, params->div, RCAR_HDMI_PHY_PLLDIVCTRL); 61 + 62 + return 0; 63 + } 64 + 65 + static const struct dw_hdmi_plat_data rcar_dw_hdmi_plat_data = { 66 + .configure_phy = rcar_hdmi_phy_configure, 67 + }; 68 + 69 + static int rcar_dw_hdmi_probe(struct platform_device *pdev) 70 + { 71 + return dw_hdmi_probe(pdev, &rcar_dw_hdmi_plat_data); 72 + } 73 + 74 + static int rcar_dw_hdmi_remove(struct platform_device *pdev) 75 + { 76 + dw_hdmi_remove(pdev); 77 + 78 + return 0; 79 + } 80 + 81 + static const struct of_device_id rcar_dw_hdmi_of_table[] = { 82 + { .compatible = "renesas,rcar-gen3-hdmi" }, 83 + { /* Sentinel */ }, 84 + }; 85 + MODULE_DEVICE_TABLE(of, rcar_dw_hdmi_of_table); 86 + 87 + static struct platform_driver rcar_dw_hdmi_platform_driver = { 88 + .probe = rcar_dw_hdmi_probe, 89 + .remove = rcar_dw_hdmi_remove, 90 + .driver = { 91 + .name = "rcar-dw-hdmi", 92 + .of_match_table = rcar_dw_hdmi_of_table, 93 + }, 94 + }; 95 + 96 + module_platform_driver(rcar_dw_hdmi_platform_driver); 97 + 98 + MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 99 + MODULE_DESCRIPTION("Renesas R-Car Gen3 HDMI Encoder Driver"); 100 + MODULE_LICENSE("GPL");