mgag200_g200eh3.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. #include <linux/pci.h>
  3. #include <drm/drm_atomic.h>
  4. #include <drm/drm_atomic_helper.h>
  5. #include <drm/drm_drv.h>
  6. #include <drm/drm_gem_atomic_helper.h>
  7. #include <drm/drm_probe_helper.h>
  8. #include "mgag200_drv.h"
  9. /*
  10. * PIXPLLC
  11. */
  12. static int mgag200_g200eh3_pixpllc_atomic_check(struct drm_crtc *crtc,
  13. struct drm_atomic_state *new_state)
  14. {
  15. static const unsigned int vcomax = 3000000;
  16. static const unsigned int vcomin = 1500000;
  17. static const unsigned int pllreffreq = 25000;
  18. struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
  19. struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
  20. long clock = new_crtc_state->mode.clock;
  21. struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
  22. unsigned int delta, tmpdelta;
  23. unsigned int testp, testm, testn;
  24. unsigned int p, m, n, s;
  25. unsigned int computed;
  26. m = n = p = s = 0;
  27. delta = 0xffffffff;
  28. testp = 0;
  29. for (testm = 150; testm >= 6; testm--) {
  30. if (clock * testm > vcomax)
  31. continue;
  32. if (clock * testm < vcomin)
  33. continue;
  34. for (testn = 120; testn >= 60; testn--) {
  35. computed = (pllreffreq * testn) / testm;
  36. if (computed > clock)
  37. tmpdelta = computed - clock;
  38. else
  39. tmpdelta = clock - computed;
  40. if (tmpdelta < delta) {
  41. delta = tmpdelta;
  42. n = testn + 1;
  43. m = testm + 1;
  44. p = testp + 1;
  45. }
  46. if (delta == 0)
  47. break;
  48. }
  49. if (delta == 0)
  50. break;
  51. }
  52. pixpllc->m = m;
  53. pixpllc->n = n;
  54. pixpllc->p = p;
  55. pixpllc->s = s;
  56. return 0;
  57. }
  58. /*
  59. * Mode-setting pipeline
  60. */
  61. static const struct drm_plane_helper_funcs mgag200_g200eh3_primary_plane_helper_funcs = {
  62. MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
  63. };
  64. static const struct drm_plane_funcs mgag200_g200eh3_primary_plane_funcs = {
  65. MGAG200_PRIMARY_PLANE_FUNCS,
  66. };
  67. static const struct drm_crtc_helper_funcs mgag200_g200eh3_crtc_helper_funcs = {
  68. MGAG200_CRTC_HELPER_FUNCS,
  69. };
  70. static const struct drm_crtc_funcs mgag200_g200eh3_crtc_funcs = {
  71. MGAG200_CRTC_FUNCS,
  72. };
  73. static const struct drm_encoder_funcs mgag200_g200eh3_dac_encoder_funcs = {
  74. MGAG200_DAC_ENCODER_FUNCS,
  75. };
  76. static const struct drm_connector_helper_funcs mgag200_g200eh3_vga_connector_helper_funcs = {
  77. MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
  78. };
  79. static const struct drm_connector_funcs mgag200_g200eh3_vga_connector_funcs = {
  80. MGAG200_VGA_CONNECTOR_FUNCS,
  81. };
  82. static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev)
  83. {
  84. struct drm_device *dev = &mdev->base;
  85. struct drm_plane *primary_plane = &mdev->primary_plane;
  86. struct drm_crtc *crtc = &mdev->crtc;
  87. struct drm_encoder *encoder = &mdev->encoder;
  88. struct mga_i2c_chan *i2c = &mdev->i2c;
  89. struct drm_connector *connector = &mdev->connector;
  90. int ret;
  91. ret = drm_universal_plane_init(dev, primary_plane, 0,
  92. &mgag200_g200eh3_primary_plane_funcs,
  93. mgag200_primary_plane_formats,
  94. mgag200_primary_plane_formats_size,
  95. mgag200_primary_plane_fmtmods,
  96. DRM_PLANE_TYPE_PRIMARY, NULL);
  97. if (ret) {
  98. drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
  99. return ret;
  100. }
  101. drm_plane_helper_add(primary_plane, &mgag200_g200eh3_primary_plane_helper_funcs);
  102. drm_plane_enable_fb_damage_clips(primary_plane);
  103. ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
  104. &mgag200_g200eh3_crtc_funcs, NULL);
  105. if (ret) {
  106. drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
  107. return ret;
  108. }
  109. drm_crtc_helper_add(crtc, &mgag200_g200eh3_crtc_helper_funcs);
  110. /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
  111. drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
  112. drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
  113. encoder->possible_crtcs = drm_crtc_mask(crtc);
  114. ret = drm_encoder_init(dev, encoder, &mgag200_g200eh3_dac_encoder_funcs,
  115. DRM_MODE_ENCODER_DAC, NULL);
  116. if (ret) {
  117. drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
  118. return ret;
  119. }
  120. ret = mgag200_i2c_init(mdev, i2c);
  121. if (ret) {
  122. drm_err(dev, "failed to add DDC bus: %d\n", ret);
  123. return ret;
  124. }
  125. ret = drm_connector_init_with_ddc(dev, connector,
  126. &mgag200_g200eh3_vga_connector_funcs,
  127. DRM_MODE_CONNECTOR_VGA,
  128. &i2c->adapter);
  129. if (ret) {
  130. drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
  131. return ret;
  132. }
  133. drm_connector_helper_add(connector, &mgag200_g200eh3_vga_connector_helper_funcs);
  134. ret = drm_connector_attach_encoder(connector, encoder);
  135. if (ret) {
  136. drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
  137. return ret;
  138. }
  139. return 0;
  140. }
  141. /*
  142. * DRM device
  143. */
  144. static const struct mgag200_device_info mgag200_g200eh3_device_info =
  145. MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false, 1, 0, false);
  146. static const struct mgag200_device_funcs mgag200_g200eh3_device_funcs = {
  147. .pixpllc_atomic_check = mgag200_g200eh3_pixpllc_atomic_check,
  148. .pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update, // same as G200EH
  149. };
  150. struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
  151. const struct drm_driver *drv)
  152. {
  153. struct mga_device *mdev;
  154. struct drm_device *dev;
  155. resource_size_t vram_available;
  156. int ret;
  157. mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base);
  158. if (IS_ERR(mdev))
  159. return mdev;
  160. dev = &mdev->base;
  161. pci_set_drvdata(pdev, dev);
  162. ret = mgag200_init_pci_options(pdev, 0x00000120, 0x0000b000);
  163. if (ret)
  164. return ERR_PTR(ret);
  165. ret = mgag200_device_preinit(mdev);
  166. if (ret)
  167. return ERR_PTR(ret);
  168. ret = mgag200_device_init(mdev, &mgag200_g200eh3_device_info,
  169. &mgag200_g200eh3_device_funcs);
  170. if (ret)
  171. return ERR_PTR(ret);
  172. mgag200_g200eh_init_registers(mdev); // same as G200EH
  173. vram_available = mgag200_device_probe_vram(mdev);
  174. ret = mgag200_mode_config_init(mdev, vram_available);
  175. if (ret)
  176. return ERR_PTR(ret);
  177. ret = mgag200_g200eh3_pipeline_init(mdev);
  178. if (ret)
  179. return ERR_PTR(ret);
  180. drm_mode_config_reset(dev);
  181. return mdev;
  182. }