mgag200_g200ew3.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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_print.h>
  8. #include <drm/drm_probe_helper.h>
  9. #include "mgag200_drv.h"
  10. static void mgag200_g200ew3_init_registers(struct mga_device *mdev)
  11. {
  12. mgag200_g200wb_init_registers(mdev); // same as G200WB
  13. WREG_ECRT(0x34, 0x5); // G200EW3 specific
  14. }
  15. /*
  16. * PIXPLLC
  17. */
  18. static int mgag200_g200ew3_pixpllc_atomic_check(struct drm_crtc *crtc,
  19. struct drm_atomic_state *new_state)
  20. {
  21. static const unsigned int vcomax = 800000;
  22. static const unsigned int vcomin = 400000;
  23. static const unsigned int pllreffreq = 25000;
  24. struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
  25. struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
  26. long clock = new_crtc_state->mode.clock;
  27. struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
  28. unsigned int delta, tmpdelta;
  29. unsigned int testp, testm, testn, testp2;
  30. unsigned int p, m, n, s;
  31. unsigned int computed;
  32. m = n = p = s = 0;
  33. delta = 0xffffffff;
  34. for (testp = 1; testp < 8; testp++) {
  35. for (testp2 = 1; testp2 < 8; testp2++) {
  36. if (testp < testp2)
  37. continue;
  38. if ((clock * testp * testp2) > vcomax)
  39. continue;
  40. if ((clock * testp * testp2) < vcomin)
  41. continue;
  42. for (testm = 1; testm < 26; testm++) {
  43. for (testn = 32; testn < 2048 ; testn++) {
  44. computed = (pllreffreq * testn) / (testm * testp * testp2);
  45. if (computed > clock)
  46. tmpdelta = computed - clock;
  47. else
  48. tmpdelta = clock - computed;
  49. if (tmpdelta < delta) {
  50. delta = tmpdelta;
  51. m = testm + 1;
  52. n = testn + 1;
  53. p = testp + 1;
  54. s = testp2;
  55. }
  56. }
  57. }
  58. }
  59. }
  60. pixpllc->m = m;
  61. pixpllc->n = n;
  62. pixpllc->p = p;
  63. pixpllc->s = s;
  64. return 0;
  65. }
  66. /*
  67. * Mode-setting pipeline
  68. */
  69. static const struct drm_plane_helper_funcs mgag200_g200ew3_primary_plane_helper_funcs = {
  70. MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
  71. };
  72. static const struct drm_plane_funcs mgag200_g200ew3_primary_plane_funcs = {
  73. MGAG200_PRIMARY_PLANE_FUNCS,
  74. };
  75. static const struct drm_crtc_helper_funcs mgag200_g200ew3_crtc_helper_funcs = {
  76. MGAG200_CRTC_HELPER_FUNCS,
  77. };
  78. static const struct drm_crtc_funcs mgag200_g200ew3_crtc_funcs = {
  79. MGAG200_CRTC_FUNCS,
  80. };
  81. static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
  82. {
  83. struct drm_device *dev = &mdev->base;
  84. struct drm_plane *primary_plane = &mdev->primary_plane;
  85. struct drm_crtc *crtc = &mdev->crtc;
  86. int ret;
  87. ret = drm_universal_plane_init(dev, primary_plane, 0,
  88. &mgag200_g200ew3_primary_plane_funcs,
  89. mgag200_primary_plane_formats,
  90. mgag200_primary_plane_formats_size,
  91. mgag200_primary_plane_fmtmods,
  92. DRM_PLANE_TYPE_PRIMARY, NULL);
  93. if (ret) {
  94. drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
  95. return ret;
  96. }
  97. drm_plane_helper_add(primary_plane, &mgag200_g200ew3_primary_plane_helper_funcs);
  98. drm_plane_enable_fb_damage_clips(primary_plane);
  99. ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
  100. &mgag200_g200ew3_crtc_funcs, NULL);
  101. if (ret) {
  102. drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
  103. return ret;
  104. }
  105. drm_crtc_helper_add(crtc, &mgag200_g200ew3_crtc_helper_funcs);
  106. /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
  107. drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
  108. drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
  109. ret = mgag200_vga_bmc_output_init(mdev);
  110. if (ret)
  111. return ret;
  112. return 0;
  113. }
  114. /*
  115. * DRM device
  116. */
  117. static const struct mgag200_device_info mgag200_g200ew3_device_info =
  118. MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, true, 0, 1, false);
  119. static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = {
  120. .pixpllc_atomic_check = mgag200_g200ew3_pixpllc_atomic_check,
  121. .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, // same as G200WB
  122. };
  123. static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev)
  124. {
  125. resource_size_t vram_size = resource_size(mdev->vram_res);
  126. if (vram_size >= 0x1000000)
  127. vram_size = vram_size - 0x400000;
  128. return mgag200_probe_vram(mdev->vram, vram_size);
  129. }
  130. struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
  131. const struct drm_driver *drv)
  132. {
  133. struct mga_device *mdev;
  134. struct drm_device *dev;
  135. resource_size_t vram_available;
  136. int ret;
  137. mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base);
  138. if (IS_ERR(mdev))
  139. return mdev;
  140. dev = &mdev->base;
  141. pci_set_drvdata(pdev, dev);
  142. ret = mgag200_init_pci_options(pdev, 0x41049120, 0x0000b000);
  143. if (ret)
  144. return ERR_PTR(ret);
  145. ret = mgag200_device_preinit(mdev);
  146. if (ret)
  147. return ERR_PTR(ret);
  148. ret = mgag200_device_init(mdev, &mgag200_g200ew3_device_info,
  149. &mgag200_g200ew3_device_funcs);
  150. if (ret)
  151. return ERR_PTR(ret);
  152. mgag200_g200ew3_init_registers(mdev);
  153. vram_available = mgag200_g200ew3_device_probe_vram(mdev);
  154. ret = mgag200_mode_config_init(mdev, vram_available);
  155. if (ret)
  156. return ERR_PTR(ret);
  157. ret = mgag200_g200ew3_pipeline_init(mdev);
  158. if (ret)
  159. return ERR_PTR(ret);
  160. drm_mode_config_reset(dev);
  161. drm_kms_helper_poll_init(dev);
  162. return mdev;
  163. }