rcar_dw_hdmi.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. #include <linux/module.h>
  14. #include <linux/platform_device.h>
  15. #include <drm/bridge/dw_hdmi.h>
  16. #define RCAR_HDMI_PHY_OPMODE_PLLCFG 0x06 /* Mode of operation and PLL dividers */
  17. #define RCAR_HDMI_PHY_PLLCURRGMPCTRL 0x10 /* PLL current and Gmp (conductance) */
  18. #define RCAR_HDMI_PHY_PLLDIVCTRL 0x11 /* PLL dividers */
  19. struct rcar_hdmi_phy_params {
  20. unsigned long mpixelclock;
  21. u16 opmode_div; /* Mode of operation and PLL dividers */
  22. u16 curr_gmp; /* PLL current and Gmp (conductance) */
  23. u16 div; /* PLL dividers */
  24. };
  25. static const struct rcar_hdmi_phy_params rcar_hdmi_phy_params[] = {
  26. { 35500000, 0x0003, 0x0344, 0x0328 },
  27. { 44900000, 0x0003, 0x0285, 0x0128 },
  28. { 71000000, 0x0002, 0x1184, 0x0314 },
  29. { 90000000, 0x0002, 0x1144, 0x0114 },
  30. { 140250000, 0x0001, 0x20c4, 0x030a },
  31. { 182750000, 0x0001, 0x2084, 0x010a },
  32. { 281250000, 0x0000, 0x0084, 0x0305 },
  33. { 297000000, 0x0000, 0x0084, 0x0105 },
  34. { ~0UL, 0x0000, 0x0000, 0x0000 },
  35. };
  36. static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi,
  37. const struct dw_hdmi_plat_data *pdata,
  38. unsigned long mpixelclock)
  39. {
  40. const struct rcar_hdmi_phy_params *params = rcar_hdmi_phy_params;
  41. for (; params->mpixelclock != ~0UL; ++params) {
  42. if (mpixelclock <= params->mpixelclock)
  43. break;
  44. }
  45. if (params->mpixelclock == ~0UL)
  46. return -EINVAL;
  47. dw_hdmi_phy_i2c_write(hdmi, params->opmode_div,
  48. RCAR_HDMI_PHY_OPMODE_PLLCFG);
  49. dw_hdmi_phy_i2c_write(hdmi, params->curr_gmp,
  50. RCAR_HDMI_PHY_PLLCURRGMPCTRL);
  51. dw_hdmi_phy_i2c_write(hdmi, params->div, RCAR_HDMI_PHY_PLLDIVCTRL);
  52. return 0;
  53. }
  54. static const struct dw_hdmi_plat_data rcar_dw_hdmi_plat_data = {
  55. .configure_phy = rcar_hdmi_phy_configure,
  56. };
  57. static int rcar_dw_hdmi_probe(struct platform_device *pdev)
  58. {
  59. struct dw_hdmi *hdmi;
  60. hdmi = dw_hdmi_probe(pdev, &rcar_dw_hdmi_plat_data);
  61. if (IS_ERR(hdmi))
  62. return PTR_ERR(hdmi);
  63. platform_set_drvdata(pdev, hdmi);
  64. return 0;
  65. }
  66. static int rcar_dw_hdmi_remove(struct platform_device *pdev)
  67. {
  68. struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
  69. dw_hdmi_remove(hdmi);
  70. return 0;
  71. }
  72. static const struct of_device_id rcar_dw_hdmi_of_table[] = {
  73. { .compatible = "renesas,rcar-gen3-hdmi" },
  74. { /* Sentinel */ },
  75. };
  76. MODULE_DEVICE_TABLE(of, rcar_dw_hdmi_of_table);
  77. static struct platform_driver rcar_dw_hdmi_platform_driver = {
  78. .probe = rcar_dw_hdmi_probe,
  79. .remove = rcar_dw_hdmi_remove,
  80. .driver = {
  81. .name = "rcar-dw-hdmi",
  82. .of_match_table = rcar_dw_hdmi_of_table,
  83. },
  84. };
  85. module_platform_driver(rcar_dw_hdmi_platform_driver);
  86. MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
  87. MODULE_DESCRIPTION("Renesas R-Car Gen3 HDMI Encoder Driver");
  88. MODULE_LICENSE("GPL");