Subversion Repositories Kolibri OS

Rev

Rev 1123 | Rev 1126 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2007-8 Advanced Micro Devices, Inc.
  3.  * Copyright 2008 Red Hat Inc.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9.  * and/or sell copies of the Software, and to permit persons to whom the
  10.  * Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice shall be included in
  13.  * all copies or substantial portions of the Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  19.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  20.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21.  * OTHER DEALINGS IN THE SOFTWARE.
  22.  *
  23.  * Authors: Dave Airlie
  24.  *          Alex Deucher
  25.  */
  26. #include <drmP.h>
  27. #include <drm_crtc_helper.h>
  28. #include "radeon_drm.h"
  29. #include "radeon_fixed.h"
  30. #include "radeon.h"
  31. #include "atom.h"
  32. #include "atom-bits.h"
  33.  
  34. static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)
  35. {
  36.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  37.         struct drm_device *dev = crtc->dev;
  38.         struct radeon_device *rdev = dev->dev_private;
  39.         int index =
  40.             GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);
  41.         ENABLE_CRTC_PS_ALLOCATION args;
  42.  
  43.         memset(&args, 0, sizeof(args));
  44.  
  45.         args.ucCRTC = radeon_crtc->crtc_id;
  46.         args.ucEnable = lock;
  47.  
  48.         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
  49. }
  50.  
  51. static void atombios_enable_crtc(struct drm_crtc *crtc, int state)
  52. {
  53.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  54.         struct drm_device *dev = crtc->dev;
  55.         struct radeon_device *rdev = dev->dev_private;
  56.         int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC);
  57.         ENABLE_CRTC_PS_ALLOCATION args;
  58.  
  59.         memset(&args, 0, sizeof(args));
  60.  
  61.         args.ucCRTC = radeon_crtc->crtc_id;
  62.         args.ucEnable = state;
  63.  
  64.         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
  65. }
  66.  
  67. static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state)
  68. {
  69.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  70.         struct drm_device *dev = crtc->dev;
  71.         struct radeon_device *rdev = dev->dev_private;
  72.         int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq);
  73.         ENABLE_CRTC_PS_ALLOCATION args;
  74.  
  75.         memset(&args, 0, sizeof(args));
  76.  
  77.         args.ucCRTC = radeon_crtc->crtc_id;
  78.         args.ucEnable = state;
  79.  
  80.         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
  81. }
  82.  
  83. static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
  84. {
  85.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  86.         struct drm_device *dev = crtc->dev;
  87.         struct radeon_device *rdev = dev->dev_private;
  88.         int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
  89.         BLANK_CRTC_PS_ALLOCATION args;
  90.  
  91.         memset(&args, 0, sizeof(args));
  92.  
  93.         args.ucCRTC = radeon_crtc->crtc_id;
  94.         args.ucBlanking = state;
  95.  
  96.         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
  97. }
  98.  
  99. void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
  100. {
  101.         struct drm_device *dev = crtc->dev;
  102.         struct radeon_device *rdev = dev->dev_private;
  103.  
  104.         switch (mode) {
  105.         case DRM_MODE_DPMS_ON:
  106.                 if (ASIC_IS_DCE3(rdev))
  107.                         atombios_enable_crtc_memreq(crtc, 1);
  108.                 atombios_enable_crtc(crtc, 1);
  109.                 atombios_blank_crtc(crtc, 0);
  110.                 break;
  111.         case DRM_MODE_DPMS_STANDBY:
  112.         case DRM_MODE_DPMS_SUSPEND:
  113.         case DRM_MODE_DPMS_OFF:
  114.                 atombios_blank_crtc(crtc, 1);
  115.                 atombios_enable_crtc(crtc, 0);
  116.                 if (ASIC_IS_DCE3(rdev))
  117.                         atombios_enable_crtc_memreq(crtc, 0);
  118.                 break;
  119.         }
  120.  
  121.         if (mode != DRM_MODE_DPMS_OFF) {
  122.                 radeon_crtc_load_lut(crtc);
  123.         }
  124. }
  125.  
  126. static void
  127. atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
  128.                              SET_CRTC_USING_DTD_TIMING_PARAMETERS * crtc_param)
  129. {
  130.         struct drm_device *dev = crtc->dev;
  131.         struct radeon_device *rdev = dev->dev_private;
  132.         SET_CRTC_USING_DTD_TIMING_PARAMETERS conv_param;
  133.         int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
  134.  
  135.         conv_param.usH_Size = cpu_to_le16(crtc_param->usH_Size);
  136.         conv_param.usH_Blanking_Time =
  137.             cpu_to_le16(crtc_param->usH_Blanking_Time);
  138.         conv_param.usV_Size = cpu_to_le16(crtc_param->usV_Size);
  139.         conv_param.usV_Blanking_Time =
  140.             cpu_to_le16(crtc_param->usV_Blanking_Time);
  141.         conv_param.usH_SyncOffset = cpu_to_le16(crtc_param->usH_SyncOffset);
  142.         conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth);
  143.         conv_param.usV_SyncOffset = cpu_to_le16(crtc_param->usV_SyncOffset);
  144.         conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth);
  145.         conv_param.susModeMiscInfo.usAccess =
  146.             cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
  147.         conv_param.ucCRTC = crtc_param->ucCRTC;
  148.  
  149.         printk("executing set crtc dtd timing\n");
  150.         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param);
  151. }
  152.  
  153. void atombios_crtc_set_timing(struct drm_crtc *crtc,
  154.                               SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *
  155.                               crtc_param)
  156. {
  157.         struct drm_device *dev = crtc->dev;
  158.         struct radeon_device *rdev = dev->dev_private;
  159.         SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION conv_param;
  160.         int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
  161.  
  162.         conv_param.usH_Total = cpu_to_le16(crtc_param->usH_Total);
  163.         conv_param.usH_Disp = cpu_to_le16(crtc_param->usH_Disp);
  164.         conv_param.usH_SyncStart = cpu_to_le16(crtc_param->usH_SyncStart);
  165.         conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth);
  166.         conv_param.usV_Total = cpu_to_le16(crtc_param->usV_Total);
  167.         conv_param.usV_Disp = cpu_to_le16(crtc_param->usV_Disp);
  168.         conv_param.usV_SyncStart = cpu_to_le16(crtc_param->usV_SyncStart);
  169.         conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth);
  170.         conv_param.susModeMiscInfo.usAccess =
  171.             cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
  172.         conv_param.ucCRTC = crtc_param->ucCRTC;
  173.         conv_param.ucOverscanRight = crtc_param->ucOverscanRight;
  174.         conv_param.ucOverscanLeft = crtc_param->ucOverscanLeft;
  175.         conv_param.ucOverscanBottom = crtc_param->ucOverscanBottom;
  176.         conv_param.ucOverscanTop = crtc_param->ucOverscanTop;
  177.         conv_param.ucReserved = crtc_param->ucReserved;
  178.  
  179.         printk("executing set crtc timing\n");
  180.         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param);
  181. }
  182.  
  183. void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
  184. {
  185.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  186.         struct drm_device *dev = crtc->dev;
  187.         struct radeon_device *rdev = dev->dev_private;
  188.         struct drm_encoder *encoder = NULL;
  189.         struct radeon_encoder *radeon_encoder = NULL;
  190.         uint8_t frev, crev;
  191.         int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
  192.         SET_PIXEL_CLOCK_PS_ALLOCATION args;
  193.         PIXEL_CLOCK_PARAMETERS *spc1_ptr;
  194.         PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
  195.         PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
  196.         uint32_t sclock = mode->clock;
  197.         uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
  198.         struct radeon_pll *pll;
  199.         int pll_flags = 0;
  200.  
  201.         memset(&args, 0, sizeof(args));
  202.  
  203.         if (ASIC_IS_AVIVO(rdev)) {
  204.                 uint32_t ss_cntl;
  205.  
  206.                 if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)        /* range limits??? */
  207.                         pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
  208.                 else
  209.                         pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
  210.  
  211.                 /* disable spread spectrum clocking for now -- thanks Hedy Lamarr */
  212.                 if (radeon_crtc->crtc_id == 0) {
  213.                         ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
  214.                         WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl & ~1);
  215.                 } else {
  216.                         ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL);
  217.                         WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl & ~1);
  218.                 }
  219.         } else {
  220.                 pll_flags |= RADEON_PLL_LEGACY;
  221.  
  222.                 if (mode->clock > 200000)       /* range limits??? */
  223.                         pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
  224.                 else
  225.                         pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
  226.  
  227.         }
  228.  
  229.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  230.                 if (encoder->crtc == crtc) {
  231.                         if (!ASIC_IS_AVIVO(rdev)) {
  232.                                 if (encoder->encoder_type !=
  233.                                     DRM_MODE_ENCODER_DAC)
  234.                                         pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
  235.                                 if (!ASIC_IS_AVIVO(rdev)
  236.                                     && (encoder->encoder_type ==
  237.                                         DRM_MODE_ENCODER_LVDS))
  238.                                         pll_flags |= RADEON_PLL_USE_REF_DIV;
  239.                         }
  240.                         radeon_encoder = to_radeon_encoder(encoder);
  241.                 }
  242.         }
  243.  
  244.         if (radeon_crtc->crtc_id == 0)
  245.                 pll = &rdev->clock.p1pll;
  246.         else
  247.                 pll = &rdev->clock.p2pll;
  248.  
  249.         radeon_compute_pll(pll, mode->clock, &sclock, &fb_div, &frac_fb_div,
  250.                            &ref_div, &post_div, pll_flags);
  251.  
  252.         atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
  253.                               &crev);
  254.  
  255.         switch (frev) {
  256.         case 1:
  257.                 switch (crev) {
  258.                 case 1:
  259.                         spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
  260.                         spc1_ptr->usPixelClock = cpu_to_le16(sclock);
  261.                         spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
  262.                         spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
  263.                         spc1_ptr->ucFracFbDiv = frac_fb_div;
  264.                         spc1_ptr->ucPostDiv = post_div;
  265.                         spc1_ptr->ucPpll =
  266.                             radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
  267.                         spc1_ptr->ucCRTC = radeon_crtc->crtc_id;
  268.                         spc1_ptr->ucRefDivSrc = 1;
  269.                         break;
  270.                 case 2:
  271.                         spc2_ptr =
  272.                             (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
  273.                         spc2_ptr->usPixelClock = cpu_to_le16(sclock);
  274.                         spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
  275.                         spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
  276.                         spc2_ptr->ucFracFbDiv = frac_fb_div;
  277.                         spc2_ptr->ucPostDiv = post_div;
  278.                         spc2_ptr->ucPpll =
  279.                             radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
  280.                         spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
  281.                         spc2_ptr->ucRefDivSrc = 1;
  282.                         break;
  283.                 case 3:
  284.                         if (!encoder)
  285.                                 return;
  286.                         spc3_ptr =
  287.                             (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
  288.                         spc3_ptr->usPixelClock = cpu_to_le16(sclock);
  289.                         spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
  290.                         spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
  291.                         spc3_ptr->ucFracFbDiv = frac_fb_div;
  292.                         spc3_ptr->ucPostDiv = post_div;
  293.                         spc3_ptr->ucPpll =
  294.                             radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
  295.                         spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
  296.                         spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
  297.                         spc3_ptr->ucEncoderMode =
  298.                             atombios_get_encoder_mode(encoder);
  299.                         break;
  300.                 default:
  301.                         DRM_ERROR("Unknown table version %d %d\n", frev, crev);
  302.                         return;
  303.                 }
  304.                 break;
  305.         default:
  306.                 DRM_ERROR("Unknown table version %d %d\n", frev, crev);
  307.                 return;
  308.         }
  309.  
  310.         printk("executing set pll\n");
  311.         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
  312. }
  313.  
  314.  
  315. int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
  316.                            struct drm_framebuffer *old_fb)
  317. {
  318.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  319.         struct drm_device *dev = crtc->dev;
  320.         struct radeon_device *rdev = dev->dev_private;
  321.         struct radeon_framebuffer *radeon_fb;
  322.         struct drm_gem_object *obj;
  323.         struct drm_radeon_gem_object *obj_priv;
  324.         uint64_t fb_location;
  325.         uint32_t fb_format, fb_pitch_pixels;
  326.  
  327.         if (!crtc->fb)
  328.                 return -EINVAL;
  329.  
  330.         radeon_fb = to_radeon_framebuffer(crtc->fb);
  331.  
  332.         obj = radeon_fb->obj;
  333.         obj_priv = obj->driver_private;
  334.  
  335. //   if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) {
  336. //       return -EINVAL;
  337. //   }
  338.  
  339.         switch (crtc->fb->bits_per_pixel) {
  340.         case 15:
  341.                 fb_format =
  342.                     AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
  343.                     AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;
  344.                 break;
  345.         case 16:
  346.                 fb_format =
  347.                     AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
  348.                     AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
  349.                 break;
  350.         case 24:
  351.         case 32:
  352.                 fb_format =
  353.                     AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
  354.                     AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
  355.                 break;
  356.         default:
  357.                 DRM_ERROR("Unsupported screen depth %d\n",
  358.                           crtc->fb->bits_per_pixel);
  359.                 return -EINVAL;
  360.         }
  361.  
  362.         /* TODO tiling */
  363.         if (radeon_crtc->crtc_id == 0)
  364.                 WREG32(AVIVO_D1VGA_CONTROL, 0);
  365.         else
  366.                 WREG32(AVIVO_D2VGA_CONTROL, 0);
  367.         WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
  368.                (u32) fb_location);
  369.         WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
  370.                radeon_crtc->crtc_offset, (u32) fb_location);
  371.         WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
  372.  
  373.         WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
  374.         WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
  375.         WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);
  376.         WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0);
  377.         WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
  378.         WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
  379.  
  380.         fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
  381.         WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
  382.         WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
  383.  
  384.         WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
  385.                crtc->mode.vdisplay);
  386.         x &= ~3;
  387.         y &= ~1;
  388.         WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
  389.                (x << 16) | y);
  390.         WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
  391.                (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
  392.  
  393.         if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
  394.                 WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
  395.                        AVIVO_D1MODE_INTERLEAVE_EN);
  396.         else
  397.                 WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
  398.  
  399.         if (old_fb && old_fb != crtc->fb) {
  400.                 radeon_fb = to_radeon_framebuffer(old_fb);
  401. //       radeon_gem_object_unpin(radeon_fb->obj);
  402.         }
  403.         return 0;
  404. }
  405.  
  406.  
  407. int atombios_crtc_mode_set(struct drm_crtc *crtc,
  408.                            struct drm_display_mode *mode,
  409.                            struct drm_display_mode *adjusted_mode,
  410.                            int x, int y, struct drm_framebuffer *old_fb)
  411. {
  412.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  413.         struct drm_device *dev = crtc->dev;
  414.         struct radeon_device *rdev = dev->dev_private;
  415.         struct drm_encoder *encoder;
  416.         SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
  417.  
  418.         /* TODO color tiling */
  419.         memset(&crtc_timing, 0, sizeof(crtc_timing));
  420.  
  421.         /* TODO tv */
  422.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  423.  
  424.         }
  425.  
  426.         crtc_timing.ucCRTC = radeon_crtc->crtc_id;
  427.         crtc_timing.usH_Total = adjusted_mode->crtc_htotal;
  428.         crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay;
  429.         crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start;
  430.         crtc_timing.usH_SyncWidth =
  431.             adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
  432.  
  433.         crtc_timing.usV_Total = adjusted_mode->crtc_vtotal;
  434.         crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay;
  435.         crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start;
  436.         crtc_timing.usV_SyncWidth =
  437.             adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
  438.  
  439.         if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
  440.                 crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
  441.  
  442.         if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
  443.                 crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
  444.  
  445.         if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
  446.                 crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
  447.  
  448.         if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
  449.                 crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
  450.  
  451.         if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
  452.                 crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
  453.  
  454.         atombios_crtc_set_pll(crtc, adjusted_mode);
  455.         atombios_crtc_set_timing(crtc, &crtc_timing);
  456.  
  457.         if (ASIC_IS_AVIVO(rdev))
  458.                 atombios_crtc_set_base(crtc, x, y, old_fb);
  459.         else {
  460.                 if (radeon_crtc->crtc_id == 0) {
  461.                         SET_CRTC_USING_DTD_TIMING_PARAMETERS crtc_dtd_timing;
  462.                         memset(&crtc_dtd_timing, 0, sizeof(crtc_dtd_timing));
  463.  
  464.                         /* setup FP shadow regs on R4xx */
  465.                         crtc_dtd_timing.ucCRTC = radeon_crtc->crtc_id;
  466.                         crtc_dtd_timing.usH_Size = adjusted_mode->crtc_hdisplay;
  467.                         crtc_dtd_timing.usV_Size = adjusted_mode->crtc_vdisplay;
  468.                         crtc_dtd_timing.usH_Blanking_Time =
  469.                             adjusted_mode->crtc_hblank_end -
  470.                             adjusted_mode->crtc_hdisplay;
  471.                         crtc_dtd_timing.usV_Blanking_Time =
  472.                             adjusted_mode->crtc_vblank_end -
  473.                             adjusted_mode->crtc_vdisplay;
  474.                         crtc_dtd_timing.usH_SyncOffset =
  475.                             adjusted_mode->crtc_hsync_start -
  476.                             adjusted_mode->crtc_hdisplay;
  477.                         crtc_dtd_timing.usV_SyncOffset =
  478.                             adjusted_mode->crtc_vsync_start -
  479.                             adjusted_mode->crtc_vdisplay;
  480.                         crtc_dtd_timing.usH_SyncWidth =
  481.                             adjusted_mode->crtc_hsync_end -
  482.                             adjusted_mode->crtc_hsync_start;
  483.                         crtc_dtd_timing.usV_SyncWidth =
  484.                             adjusted_mode->crtc_vsync_end -
  485.                             adjusted_mode->crtc_vsync_start;
  486.                         /* crtc_dtd_timing.ucH_Border = adjusted_mode->crtc_hborder; */
  487.                         /* crtc_dtd_timing.ucV_Border = adjusted_mode->crtc_vborder; */
  488.  
  489.                         if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
  490.                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
  491.                                     ATOM_VSYNC_POLARITY;
  492.  
  493.                         if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
  494.                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
  495.                                     ATOM_HSYNC_POLARITY;
  496.  
  497.                         if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
  498.                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
  499.                                     ATOM_COMPOSITESYNC;
  500.  
  501.                         if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
  502.                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
  503.                                     ATOM_INTERLACE;
  504.  
  505.                         if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
  506.                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
  507.                                     ATOM_DOUBLE_CLOCK_MODE;
  508.  
  509.                         atombios_set_crtc_dtd_timing(crtc, &crtc_dtd_timing);
  510.                 }
  511.                 radeon_crtc_set_base(crtc, x, y, old_fb);
  512.                 radeon_legacy_atom_set_surface(crtc);
  513.         }
  514.         return 0;
  515. }
  516.  
  517. static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
  518.                                      struct drm_display_mode *mode,
  519.                                      struct drm_display_mode *adjusted_mode)
  520. {
  521.         return true;
  522. }
  523.  
  524. static void atombios_crtc_prepare(struct drm_crtc *crtc)
  525. {
  526.         atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
  527.         atombios_lock_crtc(crtc, 1);
  528. }
  529.  
  530. static void atombios_crtc_commit(struct drm_crtc *crtc)
  531. {
  532.         atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
  533.         atombios_lock_crtc(crtc, 0);
  534. }
  535.  
  536. static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
  537.         .dpms = atombios_crtc_dpms,
  538.         .mode_fixup = atombios_crtc_mode_fixup,
  539.         .mode_set = atombios_crtc_mode_set,
  540.         .mode_set_base = atombios_crtc_set_base,
  541.         .prepare = atombios_crtc_prepare,
  542.         .commit = atombios_crtc_commit,
  543. };
  544.  
  545. void radeon_atombios_init_crtc(struct drm_device *dev,
  546.                                struct radeon_crtc *radeon_crtc)
  547. {
  548.         if (radeon_crtc->crtc_id == 1)
  549.                 radeon_crtc->crtc_offset =
  550.                     AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
  551.         drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
  552.  
  553.     dbgprintf("done %s\n",__FUNCTION__);
  554.  
  555. }
  556.  
  557. void radeon_init_disp_bw_avivo(struct drm_device *dev,
  558.                                struct drm_display_mode *mode1,
  559.                                uint32_t pixel_bytes1,
  560.                                struct drm_display_mode *mode2,
  561.                                uint32_t pixel_bytes2)
  562. {
  563.         struct radeon_device *rdev = dev->dev_private;
  564.         fixed20_12 min_mem_eff;
  565.         fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff;
  566.         fixed20_12 sclk_ff, mclk_ff;
  567.         uint32_t dc_lb_memory_split, temp;
  568.  
  569.         min_mem_eff.full = rfixed_const_8(0);
  570.         if (rdev->disp_priority == 2) {
  571.                 uint32_t mc_init_misc_lat_timer = 0;
  572.                 if (rdev->family == CHIP_RV515)
  573.                         mc_init_misc_lat_timer =
  574.                             RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER);
  575.                 else if (rdev->family == CHIP_RS690)
  576.                         mc_init_misc_lat_timer =
  577.                             RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER);
  578.  
  579.                 mc_init_misc_lat_timer &=
  580.                     ~(R300_MC_DISP1R_INIT_LAT_MASK <<
  581.                       R300_MC_DISP1R_INIT_LAT_SHIFT);
  582.                 mc_init_misc_lat_timer &=
  583.                     ~(R300_MC_DISP0R_INIT_LAT_MASK <<
  584.                       R300_MC_DISP0R_INIT_LAT_SHIFT);
  585.  
  586.                 if (mode2)
  587.                         mc_init_misc_lat_timer |=
  588.                             (1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
  589.                 if (mode1)
  590.                         mc_init_misc_lat_timer |=
  591.                             (1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
  592.  
  593.                 if (rdev->family == CHIP_RV515)
  594.                         WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER,
  595.                                   mc_init_misc_lat_timer);
  596.                 else if (rdev->family == CHIP_RS690)
  597.                         WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER,
  598.                                   mc_init_misc_lat_timer);
  599.         }
  600.  
  601.         /*
  602.          * determine is there is enough bw for current mode
  603.          */
  604.         temp_ff.full = rfixed_const(100);
  605.         mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
  606.         mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
  607.         sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
  608.         sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
  609.  
  610.         temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
  611.         temp_ff.full = rfixed_const(temp);
  612.         mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
  613.         mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
  614.  
  615.         pix_clk.full = 0;
  616.         pix_clk2.full = 0;
  617.         peak_disp_bw.full = 0;
  618.         if (mode1) {
  619.                 temp_ff.full = rfixed_const(1000);
  620.                 pix_clk.full = rfixed_const(mode1->clock);      /* convert to fixed point */
  621.                 pix_clk.full = rfixed_div(pix_clk, temp_ff);
  622.                 temp_ff.full = rfixed_const(pixel_bytes1);
  623.                 peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
  624.         }
  625.         if (mode2) {
  626.                 temp_ff.full = rfixed_const(1000);
  627.                 pix_clk2.full = rfixed_const(mode2->clock);     /* convert to fixed point */
  628.                 pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
  629.                 temp_ff.full = rfixed_const(pixel_bytes2);
  630.                 peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
  631.         }
  632.  
  633.         if (peak_disp_bw.full >= mem_bw.full) {
  634.                 DRM_ERROR
  635.                     ("You may not have enough display bandwidth for current mode\n"
  636.                      "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
  637.                 printk("peak disp bw %d, mem_bw %d\n",
  638.                        rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw));
  639.         }
  640.  
  641.         /*
  642.          * Line Buffer Setup
  643.          * There is a single line buffer shared by both display controllers.
  644.          * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display
  645.          * controllers.  The paritioning can either be done manually or via one of four
  646.          * preset allocations specified in bits 1:0:
  647.          * 0 - line buffer is divided in half and shared between each display controller
  648.          * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
  649.          * 2 - D1 gets the whole buffer
  650.          * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
  651.          * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode.
  652.          * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits
  653.          * 14:4; D2 allocation follows D1.
  654.          */
  655.  
  656.         /* is auto or manual better ? */
  657.         dc_lb_memory_split =
  658.             RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
  659.         dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
  660. #if 1
  661.         /* auto */
  662.         if (mode1 && mode2) {
  663.                 if (mode1->hdisplay > mode2->hdisplay) {
  664.                         if (mode1->hdisplay > 2560)
  665.                                 dc_lb_memory_split |=
  666.                                     AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
  667.                         else
  668.                                 dc_lb_memory_split |=
  669.                                     AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
  670.                 } else if (mode2->hdisplay > mode1->hdisplay) {
  671.                         if (mode2->hdisplay > 2560)
  672.                                 dc_lb_memory_split |=
  673.                                     AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
  674.                         else
  675.                                 dc_lb_memory_split |=
  676.                                     AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
  677.                 } else
  678.                         dc_lb_memory_split |=
  679.                             AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
  680.         } else if (mode1) {
  681.                 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY;
  682.         } else if (mode2) {
  683.                 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
  684.         }
  685. #else
  686.         /* manual */
  687.         dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
  688.         dc_lb_memory_split &=
  689.             ~(AVIVO_DC_LB_DISP1_END_ADR_MASK <<
  690.               AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
  691.         if (mode1) {
  692.                 dc_lb_memory_split |=
  693.                     ((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK)
  694.                      << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
  695.         } else if (mode2) {
  696.                 dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
  697.         }
  698. #endif
  699.         WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
  700. }
  701.