xref: /openbsd-src/sys/dev/pci/drm/radeon/radeon_legacy_crtc.c (revision f005ef32267c16bdb134f0e9fa4477dbe07c263a)
11099013bSjsg /*
21099013bSjsg  * Copyright 2007-8 Advanced Micro Devices, Inc.
31099013bSjsg  * Copyright 2008 Red Hat Inc.
41099013bSjsg  *
51099013bSjsg  * Permission is hereby granted, free of charge, to any person obtaining a
61099013bSjsg  * copy of this software and associated documentation files (the "Software"),
71099013bSjsg  * to deal in the Software without restriction, including without limitation
81099013bSjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
91099013bSjsg  * and/or sell copies of the Software, and to permit persons to whom the
101099013bSjsg  * Software is furnished to do so, subject to the following conditions:
111099013bSjsg  *
121099013bSjsg  * The above copyright notice and this permission notice shall be included in
131099013bSjsg  * all copies or substantial portions of the Software.
141099013bSjsg  *
151099013bSjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161099013bSjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
171099013bSjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
181099013bSjsg  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
191099013bSjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
201099013bSjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
211099013bSjsg  * OTHER DEALINGS IN THE SOFTWARE.
221099013bSjsg  *
231099013bSjsg  * Authors: Dave Airlie
241099013bSjsg  *          Alex Deucher
251099013bSjsg  */
26c349dbc7Sjsg 
277f4dd379Sjsg #include <drm/drm_fixed.h>
28c349dbc7Sjsg #include <drm/drm_fourcc.h>
291bb76ff1Sjsg #include <drm/drm_framebuffer.h>
30*f005ef32Sjsg #include <drm/drm_modeset_helper_vtables.h>
31c349dbc7Sjsg #include <drm/drm_vblank.h>
32c349dbc7Sjsg #include <drm/radeon_drm.h>
33c349dbc7Sjsg 
341099013bSjsg #include "atom.h"
35c349dbc7Sjsg #include "radeon.h"
361099013bSjsg 
radeon_overscan_setup(struct drm_crtc * crtc,struct drm_display_mode * mode)371099013bSjsg static void radeon_overscan_setup(struct drm_crtc *crtc,
381099013bSjsg 				  struct drm_display_mode *mode)
391099013bSjsg {
401099013bSjsg 	struct drm_device *dev = crtc->dev;
411099013bSjsg 	struct radeon_device *rdev = dev->dev_private;
421099013bSjsg 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
431099013bSjsg 
441099013bSjsg 	WREG32(RADEON_OVR_CLR + radeon_crtc->crtc_offset, 0);
451099013bSjsg 	WREG32(RADEON_OVR_WID_LEFT_RIGHT + radeon_crtc->crtc_offset, 0);
461099013bSjsg 	WREG32(RADEON_OVR_WID_TOP_BOTTOM + radeon_crtc->crtc_offset, 0);
471099013bSjsg }
481099013bSjsg 
radeon_legacy_rmx_mode_set(struct drm_crtc * crtc,struct drm_display_mode * mode)491099013bSjsg static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
501099013bSjsg 				       struct drm_display_mode *mode)
511099013bSjsg {
521099013bSjsg 	struct drm_device *dev = crtc->dev;
531099013bSjsg 	struct radeon_device *rdev = dev->dev_private;
541099013bSjsg 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
551099013bSjsg 	int xres = mode->hdisplay;
561099013bSjsg 	int yres = mode->vdisplay;
571099013bSjsg 	bool hscale = true, vscale = true;
581099013bSjsg 	int hsync_wid;
591099013bSjsg 	int vsync_wid;
601099013bSjsg 	int hsync_start;
611099013bSjsg 	int blank_width;
621099013bSjsg 	u32 scale, inc, crtc_more_cntl;
631099013bSjsg 	u32 fp_horz_stretch, fp_vert_stretch, fp_horz_vert_active;
641099013bSjsg 	u32 fp_h_sync_strt_wid, fp_crtc_h_total_disp;
651099013bSjsg 	u32 fp_v_sync_strt_wid, fp_crtc_v_total_disp;
661099013bSjsg 	struct drm_display_mode *native_mode = &radeon_crtc->native_mode;
671099013bSjsg 
681099013bSjsg 	fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) &
691099013bSjsg 		(RADEON_VERT_STRETCH_RESERVED |
701099013bSjsg 		 RADEON_VERT_AUTO_RATIO_INC);
711099013bSjsg 	fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) &
721099013bSjsg 		(RADEON_HORZ_FP_LOOP_STRETCH |
731099013bSjsg 		 RADEON_HORZ_AUTO_RATIO_INC);
741099013bSjsg 
751099013bSjsg 	crtc_more_cntl = 0;
761099013bSjsg 	if ((rdev->family == CHIP_RS100) ||
771099013bSjsg 	    (rdev->family == CHIP_RS200)) {
781099013bSjsg 		/* This is to workaround the asic bug for RMX, some versions
791099013bSjsg 		   of BIOS dosen't have this register initialized correctly. */
801099013bSjsg 		crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
811099013bSjsg 	}
821099013bSjsg 
831099013bSjsg 
841099013bSjsg 	fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
851099013bSjsg 				| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
861099013bSjsg 
871099013bSjsg 	hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
881099013bSjsg 	if (!hsync_wid)
891099013bSjsg 		hsync_wid = 1;
901099013bSjsg 	hsync_start = mode->crtc_hsync_start - 8;
911099013bSjsg 
921099013bSjsg 	fp_h_sync_strt_wid = ((hsync_start & 0x1fff)
931099013bSjsg 			      | ((hsync_wid & 0x3f) << 16)
941099013bSjsg 			      | ((mode->flags & DRM_MODE_FLAG_NHSYNC)
951099013bSjsg 				 ? RADEON_CRTC_H_SYNC_POL
961099013bSjsg 				 : 0));
971099013bSjsg 
981099013bSjsg 	fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
991099013bSjsg 				| ((mode->crtc_vdisplay - 1) << 16));
1001099013bSjsg 
1011099013bSjsg 	vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
1021099013bSjsg 	if (!vsync_wid)
1031099013bSjsg 		vsync_wid = 1;
1041099013bSjsg 
1051099013bSjsg 	fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
1061099013bSjsg 			      | ((vsync_wid & 0x1f) << 16)
1071099013bSjsg 			      | ((mode->flags & DRM_MODE_FLAG_NVSYNC)
1081099013bSjsg 				 ? RADEON_CRTC_V_SYNC_POL
1091099013bSjsg 				 : 0));
1101099013bSjsg 
1111099013bSjsg 	fp_horz_vert_active = 0;
1121099013bSjsg 
1131099013bSjsg 	if (native_mode->hdisplay == 0 ||
1141099013bSjsg 	    native_mode->vdisplay == 0) {
1151099013bSjsg 		hscale = false;
1161099013bSjsg 		vscale = false;
1171099013bSjsg 	} else {
1181099013bSjsg 		if (xres > native_mode->hdisplay)
1191099013bSjsg 			xres = native_mode->hdisplay;
1201099013bSjsg 		if (yres > native_mode->vdisplay)
1211099013bSjsg 			yres = native_mode->vdisplay;
1221099013bSjsg 
1231099013bSjsg 		if (xres == native_mode->hdisplay)
1241099013bSjsg 			hscale = false;
1251099013bSjsg 		if (yres == native_mode->vdisplay)
1261099013bSjsg 			vscale = false;
1271099013bSjsg 	}
1281099013bSjsg 
1291099013bSjsg 	switch (radeon_crtc->rmx_type) {
1301099013bSjsg 	case RMX_FULL:
1311099013bSjsg 	case RMX_ASPECT:
1321099013bSjsg 		if (!hscale)
1331099013bSjsg 			fp_horz_stretch |= ((xres/8-1) << 16);
1341099013bSjsg 		else {
1351099013bSjsg 			inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
1361099013bSjsg 			scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
1371099013bSjsg 				/ native_mode->hdisplay + 1;
1381099013bSjsg 			fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
1391099013bSjsg 					RADEON_HORZ_STRETCH_BLEND |
1401099013bSjsg 					RADEON_HORZ_STRETCH_ENABLE |
1411099013bSjsg 					((native_mode->hdisplay/8-1) << 16));
1421099013bSjsg 		}
1431099013bSjsg 
1441099013bSjsg 		if (!vscale)
1451099013bSjsg 			fp_vert_stretch |= ((yres-1) << 12);
1461099013bSjsg 		else {
1471099013bSjsg 			inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
1481099013bSjsg 			scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
1491099013bSjsg 				/ native_mode->vdisplay + 1;
1501099013bSjsg 			fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
1511099013bSjsg 					RADEON_VERT_STRETCH_ENABLE |
1521099013bSjsg 					RADEON_VERT_STRETCH_BLEND |
1531099013bSjsg 					((native_mode->vdisplay-1) << 12));
1541099013bSjsg 		}
1551099013bSjsg 		break;
1561099013bSjsg 	case RMX_CENTER:
1571099013bSjsg 		fp_horz_stretch |= ((xres/8-1) << 16);
1581099013bSjsg 		fp_vert_stretch |= ((yres-1) << 12);
1591099013bSjsg 
1601099013bSjsg 		crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN |
1611099013bSjsg 				RADEON_CRTC_AUTO_VERT_CENTER_EN);
1621099013bSjsg 
1631099013bSjsg 		blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8;
1641099013bSjsg 		if (blank_width > 110)
1651099013bSjsg 			blank_width = 110;
1661099013bSjsg 
1671099013bSjsg 		fp_crtc_h_total_disp = (((blank_width) & 0x3ff)
1681099013bSjsg 				| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
1691099013bSjsg 
1701099013bSjsg 		hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
1711099013bSjsg 		if (!hsync_wid)
1721099013bSjsg 			hsync_wid = 1;
1731099013bSjsg 
1741099013bSjsg 		fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff)
1751099013bSjsg 				| ((hsync_wid & 0x3f) << 16)
1761099013bSjsg 				| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
1771099013bSjsg 					? RADEON_CRTC_H_SYNC_POL
1781099013bSjsg 					: 0));
1791099013bSjsg 
1801099013bSjsg 		fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff)
1811099013bSjsg 				| ((mode->crtc_vdisplay - 1) << 16));
1821099013bSjsg 
1831099013bSjsg 		vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
1841099013bSjsg 		if (!vsync_wid)
1851099013bSjsg 			vsync_wid = 1;
1861099013bSjsg 
1871099013bSjsg 		fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff)
1881099013bSjsg 					| ((vsync_wid & 0x1f) << 16)
1891099013bSjsg 					| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
1901099013bSjsg 						? RADEON_CRTC_V_SYNC_POL
1911099013bSjsg 						: 0)));
1921099013bSjsg 
1931099013bSjsg 		fp_horz_vert_active = (((native_mode->vdisplay) & 0xfff) |
1941099013bSjsg 				(((native_mode->hdisplay / 8) & 0x1ff) << 16));
1951099013bSjsg 		break;
1961099013bSjsg 	case RMX_OFF:
1971099013bSjsg 	default:
1981099013bSjsg 		fp_horz_stretch |= ((xres/8-1) << 16);
1991099013bSjsg 		fp_vert_stretch |= ((yres-1) << 12);
2001099013bSjsg 		break;
2011099013bSjsg 	}
2021099013bSjsg 
2031099013bSjsg 	WREG32(RADEON_FP_HORZ_STRETCH,      fp_horz_stretch);
2041099013bSjsg 	WREG32(RADEON_FP_VERT_STRETCH,      fp_vert_stretch);
2051099013bSjsg 	WREG32(RADEON_CRTC_MORE_CNTL,       crtc_more_cntl);
2061099013bSjsg 	WREG32(RADEON_FP_HORZ_VERT_ACTIVE,  fp_horz_vert_active);
2071099013bSjsg 	WREG32(RADEON_FP_H_SYNC_STRT_WID,   fp_h_sync_strt_wid);
2081099013bSjsg 	WREG32(RADEON_FP_V_SYNC_STRT_WID,   fp_v_sync_strt_wid);
2091099013bSjsg 	WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp);
2101099013bSjsg 	WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp);
2111099013bSjsg }
2121099013bSjsg 
radeon_pll_wait_for_read_update_complete(struct drm_device * dev)2131099013bSjsg static void radeon_pll_wait_for_read_update_complete(struct drm_device *dev)
2141099013bSjsg {
2151099013bSjsg 	struct radeon_device *rdev = dev->dev_private;
2161099013bSjsg 	int i = 0;
2171099013bSjsg 
2181099013bSjsg 	/* FIXME: Certain revisions of R300 can't recover here.  Not sure of
2191099013bSjsg 	   the cause yet, but this workaround will mask the problem for now.
2201099013bSjsg 	   Other chips usually will pass at the very first test, so the
2211099013bSjsg 	   workaround shouldn't have any effect on them. */
2221099013bSjsg 	for (i = 0;
2231099013bSjsg 	     (i < 10000 &&
2241099013bSjsg 	      RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
2251099013bSjsg 	     i++);
2261099013bSjsg }
2271099013bSjsg 
radeon_pll_write_update(struct drm_device * dev)2281099013bSjsg static void radeon_pll_write_update(struct drm_device *dev)
2291099013bSjsg {
2301099013bSjsg 	struct radeon_device *rdev = dev->dev_private;
2311099013bSjsg 
2321099013bSjsg 	while (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
2331099013bSjsg 
2341099013bSjsg 	WREG32_PLL_P(RADEON_PPLL_REF_DIV,
2351099013bSjsg 			   RADEON_PPLL_ATOMIC_UPDATE_W,
2361099013bSjsg 			   ~(RADEON_PPLL_ATOMIC_UPDATE_W));
2371099013bSjsg }
2381099013bSjsg 
radeon_pll2_wait_for_read_update_complete(struct drm_device * dev)2391099013bSjsg static void radeon_pll2_wait_for_read_update_complete(struct drm_device *dev)
2401099013bSjsg {
2411099013bSjsg 	struct radeon_device *rdev = dev->dev_private;
2421099013bSjsg 	int i = 0;
2431099013bSjsg 
2441099013bSjsg 
2451099013bSjsg 	/* FIXME: Certain revisions of R300 can't recover here.  Not sure of
2461099013bSjsg 	   the cause yet, but this workaround will mask the problem for now.
2471099013bSjsg 	   Other chips usually will pass at the very first test, so the
2481099013bSjsg 	   workaround shouldn't have any effect on them. */
2491099013bSjsg 	for (i = 0;
2501099013bSjsg 	     (i < 10000 &&
2511099013bSjsg 	      RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
2521099013bSjsg 	     i++);
2531099013bSjsg }
2541099013bSjsg 
radeon_pll2_write_update(struct drm_device * dev)2551099013bSjsg static void radeon_pll2_write_update(struct drm_device *dev)
2561099013bSjsg {
2571099013bSjsg 	struct radeon_device *rdev = dev->dev_private;
2581099013bSjsg 
2591099013bSjsg 	while (RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
2601099013bSjsg 
2611099013bSjsg 	WREG32_PLL_P(RADEON_P2PLL_REF_DIV,
2621099013bSjsg 			   RADEON_P2PLL_ATOMIC_UPDATE_W,
2631099013bSjsg 			   ~(RADEON_P2PLL_ATOMIC_UPDATE_W));
2641099013bSjsg }
2651099013bSjsg 
radeon_compute_pll_gain(uint16_t ref_freq,uint16_t ref_div,uint16_t fb_div)2661099013bSjsg static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div,
2671099013bSjsg 				       uint16_t fb_div)
2681099013bSjsg {
2691099013bSjsg 	unsigned int vcoFreq;
2701099013bSjsg 
2711099013bSjsg 	if (!ref_div)
2721099013bSjsg 		return 1;
2731099013bSjsg 
2741099013bSjsg 	vcoFreq = ((unsigned)ref_freq * fb_div) / ref_div;
2751099013bSjsg 
2761099013bSjsg 	/*
2771099013bSjsg 	 * This is horribly crude: the VCO frequency range is divided into
2781099013bSjsg 	 * 3 parts, each part having a fixed PLL gain value.
2791099013bSjsg 	 */
2801099013bSjsg 	if (vcoFreq >= 30000)
2811099013bSjsg 		/*
2821099013bSjsg 		 * [300..max] MHz : 7
2831099013bSjsg 		 */
2841099013bSjsg 		return 7;
2851099013bSjsg 	else if (vcoFreq >= 18000)
2861099013bSjsg 		/*
2871099013bSjsg 		 * [180..300) MHz : 4
2881099013bSjsg 		 */
2891099013bSjsg 		return 4;
2901099013bSjsg 	else
2911099013bSjsg 		/*
2921099013bSjsg 		 * [0..180) MHz : 1
2931099013bSjsg 		 */
2941099013bSjsg 		return 1;
2951099013bSjsg }
2961099013bSjsg 
radeon_crtc_dpms(struct drm_crtc * crtc,int mode)2971099013bSjsg static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
2981099013bSjsg {
2991099013bSjsg 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
3001099013bSjsg 	struct drm_device *dev = crtc->dev;
3011099013bSjsg 	struct radeon_device *rdev = dev->dev_private;
3021099013bSjsg 	uint32_t crtc_ext_cntl = 0;
3031099013bSjsg 	uint32_t mask;
3041099013bSjsg 
3051099013bSjsg 	if (radeon_crtc->crtc_id)
3061099013bSjsg 		mask = (RADEON_CRTC2_DISP_DIS |
3071099013bSjsg 			RADEON_CRTC2_VSYNC_DIS |
3081099013bSjsg 			RADEON_CRTC2_HSYNC_DIS |
3091099013bSjsg 			RADEON_CRTC2_DISP_REQ_EN_B);
3101099013bSjsg 	else
3111099013bSjsg 		mask = (RADEON_CRTC_DISPLAY_DIS |
3121099013bSjsg 			RADEON_CRTC_VSYNC_DIS |
3131099013bSjsg 			RADEON_CRTC_HSYNC_DIS);
3141099013bSjsg 
3151099013bSjsg 	/*
3161099013bSjsg 	 * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC.
3171099013bSjsg 	 * Therefore it is set in the DAC DMPS function.
3181099013bSjsg 	 * This is different for GPU's with a single CRTC but a primary and a
3191099013bSjsg 	 * TV DAC: here it controls the single CRTC no matter where it is
3201099013bSjsg 	 * routed. Therefore we set it here.
3211099013bSjsg 	 */
3221099013bSjsg 	if (rdev->flags & RADEON_SINGLE_CRTC)
3231099013bSjsg 		crtc_ext_cntl = RADEON_CRTC_CRT_ON;
3241099013bSjsg 
3251099013bSjsg 	switch (mode) {
3261099013bSjsg 	case DRM_MODE_DPMS_ON:
3271099013bSjsg 		radeon_crtc->enabled = true;
3281099013bSjsg 		/* adjust pm to dpms changes BEFORE enabling crtcs */
3291099013bSjsg 		radeon_pm_compute_clocks(rdev);
3301099013bSjsg 		if (radeon_crtc->crtc_id)
3311099013bSjsg 			WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask));
3321099013bSjsg 		else {
3331099013bSjsg 			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
3341099013bSjsg 									 RADEON_CRTC_DISP_REQ_EN_B));
3351099013bSjsg 			WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));
3361099013bSjsg 		}
3377f4dd379Sjsg 		if (dev->num_crtcs > radeon_crtc->crtc_id)
3387f4dd379Sjsg 			drm_crtc_vblank_on(crtc);
3391099013bSjsg 		radeon_crtc_load_lut(crtc);
3401099013bSjsg 		break;
3411099013bSjsg 	case DRM_MODE_DPMS_STANDBY:
3421099013bSjsg 	case DRM_MODE_DPMS_SUSPEND:
3431099013bSjsg 	case DRM_MODE_DPMS_OFF:
3447f4dd379Sjsg 		if (dev->num_crtcs > radeon_crtc->crtc_id)
3457f4dd379Sjsg 			drm_crtc_vblank_off(crtc);
3461099013bSjsg 		if (radeon_crtc->crtc_id)
3471099013bSjsg 			WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask));
3481099013bSjsg 		else {
3491099013bSjsg 			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
3501099013bSjsg 										    RADEON_CRTC_DISP_REQ_EN_B));
3511099013bSjsg 			WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));
3521099013bSjsg 		}
3531099013bSjsg 		radeon_crtc->enabled = false;
3541099013bSjsg 		/* adjust pm to dpms changes AFTER disabling crtcs */
3551099013bSjsg 		radeon_pm_compute_clocks(rdev);
3561099013bSjsg 		break;
3571099013bSjsg 	}
3581099013bSjsg }
3591099013bSjsg 
radeon_crtc_set_base(struct drm_crtc * crtc,int x,int y,struct drm_framebuffer * old_fb)3601099013bSjsg int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
3611099013bSjsg 			 struct drm_framebuffer *old_fb)
3621099013bSjsg {
3631099013bSjsg 	return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0);
3641099013bSjsg }
3651099013bSjsg 
radeon_crtc_set_base_atomic(struct drm_crtc * crtc,struct drm_framebuffer * fb,int x,int y,enum mode_set_atomic state)3661099013bSjsg int radeon_crtc_set_base_atomic(struct drm_crtc *crtc,
3671099013bSjsg 				struct drm_framebuffer *fb,
3681099013bSjsg 				int x, int y, enum mode_set_atomic state)
3691099013bSjsg {
3701099013bSjsg 	return radeon_crtc_do_set_base(crtc, fb, x, y, 1);
3711099013bSjsg }
3721099013bSjsg 
radeon_crtc_do_set_base(struct drm_crtc * crtc,struct drm_framebuffer * fb,int x,int y,int atomic)3731099013bSjsg int radeon_crtc_do_set_base(struct drm_crtc *crtc,
3741099013bSjsg 			 struct drm_framebuffer *fb,
3751099013bSjsg 			 int x, int y, int atomic)
3761099013bSjsg {
3771099013bSjsg 	struct drm_device *dev = crtc->dev;
3781099013bSjsg 	struct radeon_device *rdev = dev->dev_private;
3791099013bSjsg 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
3801099013bSjsg 	struct drm_framebuffer *target_fb;
3814a5d3272Skettenis 	struct drm_gem_object *obj;
3821099013bSjsg 	struct radeon_bo *rbo;
3831099013bSjsg 	uint64_t base;
3841099013bSjsg 	uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0;
3851099013bSjsg 	uint32_t crtc_pitch, pitch_pixels;
3861099013bSjsg 	uint32_t tiling_flags;
3871099013bSjsg 	int format;
3881099013bSjsg 	uint32_t gen_cntl_reg, gen_cntl_val;
3891099013bSjsg 	int r;
3901099013bSjsg 
3911099013bSjsg 	DRM_DEBUG_KMS("\n");
3921099013bSjsg 	/* no fb bound */
3933253c27bSkettenis 	if (!atomic && !crtc->primary->fb) {
3941099013bSjsg 		DRM_DEBUG_KMS("No FB bound\n");
3951099013bSjsg 		return 0;
3961099013bSjsg 	}
3971099013bSjsg 
3987f4dd379Sjsg 	if (atomic)
3991099013bSjsg 		target_fb = fb;
4007f4dd379Sjsg 	else
4013253c27bSkettenis 		target_fb = crtc->primary->fb;
4021099013bSjsg 
4037f4dd379Sjsg 	switch (target_fb->format->cpp[0] * 8) {
4041099013bSjsg 	case 8:
4051099013bSjsg 		format = 2;
4061099013bSjsg 		break;
4071099013bSjsg 	case 15:      /*  555 */
4081099013bSjsg 		format = 3;
4091099013bSjsg 		break;
4101099013bSjsg 	case 16:      /*  565 */
4111099013bSjsg 		format = 4;
4121099013bSjsg 		break;
4131099013bSjsg 	case 24:      /*  RGB */
4141099013bSjsg 		format = 5;
4151099013bSjsg 		break;
4161099013bSjsg 	case 32:      /* xRGB */
4171099013bSjsg 		format = 6;
4181099013bSjsg 		break;
4191099013bSjsg 	default:
4201099013bSjsg 		return false;
4211099013bSjsg 	}
4221099013bSjsg 
4231099013bSjsg 	/* Pin framebuffer & get tilling informations */
4247f4dd379Sjsg 	obj = target_fb->obj[0];
4251099013bSjsg 	rbo = gem_to_radeon_bo(obj);
426c252e55eSjsg retry:
4271099013bSjsg 	r = radeon_bo_reserve(rbo, false);
4281099013bSjsg 	if (unlikely(r != 0))
4291099013bSjsg 		return r;
4301099013bSjsg 	/* Only 27 bit offset for legacy CRTC */
4311099013bSjsg 	r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, 1 << 27,
4321099013bSjsg 				     &base);
4331099013bSjsg 	if (unlikely(r != 0)) {
4341099013bSjsg 		radeon_bo_unreserve(rbo);
435c252e55eSjsg 
436c252e55eSjsg 		/* On old GPU like RN50 with little vram pining can fails because
437c252e55eSjsg 		 * current fb is taking all space needed. So instead of unpining
438c252e55eSjsg 		 * the old buffer after pining the new one, first unpin old one
439c252e55eSjsg 		 * and then retry pining new one.
440c252e55eSjsg 		 *
441c252e55eSjsg 		 * As only master can set mode only master can pin and it is
442c252e55eSjsg 		 * unlikely the master client will race with itself especialy
443c252e55eSjsg 		 * on those old gpu with single crtc.
444c252e55eSjsg 		 *
445c252e55eSjsg 		 * We don't shutdown the display controller because new buffer
446c252e55eSjsg 		 * will end up in same spot.
447c252e55eSjsg 		 */
4483253c27bSkettenis 		if (!atomic && fb && fb != crtc->primary->fb) {
449c252e55eSjsg 			struct radeon_bo *old_rbo;
450c252e55eSjsg 			unsigned long nsize, osize;
451c252e55eSjsg 
4527f4dd379Sjsg 			old_rbo = gem_to_radeon_bo(fb->obj[0]);
453c252e55eSjsg 			osize = radeon_bo_size(old_rbo);
454c252e55eSjsg 			nsize = radeon_bo_size(rbo);
455c252e55eSjsg 			if (nsize <= osize && !radeon_bo_reserve(old_rbo, false)) {
456c252e55eSjsg 				radeon_bo_unpin(old_rbo);
457c252e55eSjsg 				radeon_bo_unreserve(old_rbo);
458c252e55eSjsg 				fb = NULL;
459c252e55eSjsg 				goto retry;
460c252e55eSjsg 			}
461c252e55eSjsg 		}
4621099013bSjsg 		return -EINVAL;
4631099013bSjsg 	}
4641099013bSjsg 	radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
4651099013bSjsg 	radeon_bo_unreserve(rbo);
4661099013bSjsg 	if (tiling_flags & RADEON_TILING_MICRO)
4671099013bSjsg 		DRM_ERROR("trying to scanout microtiled buffer\n");
4681099013bSjsg 
4691099013bSjsg 	/* if scanout was in GTT this really wouldn't work */
4701099013bSjsg 	/* crtc offset is from display base addr not FB location */
4711099013bSjsg 	radeon_crtc->legacy_display_base_addr = rdev->mc.vram_start;
4721099013bSjsg 
4731099013bSjsg 	base -= radeon_crtc->legacy_display_base_addr;
4741099013bSjsg 
4751099013bSjsg 	crtc_offset_cntl = 0;
4761099013bSjsg 
4777f4dd379Sjsg 	pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0];
4787f4dd379Sjsg 	crtc_pitch = DIV_ROUND_UP(pitch_pixels * target_fb->format->cpp[0] * 8,
4797f4dd379Sjsg 				  target_fb->format->cpp[0] * 8 * 8);
4801099013bSjsg 	crtc_pitch |= crtc_pitch << 16;
4811099013bSjsg 
4821099013bSjsg 	crtc_offset_cntl |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN;
4831099013bSjsg 	if (tiling_flags & RADEON_TILING_MACRO) {
4841099013bSjsg 		if (ASIC_IS_R300(rdev))
4851099013bSjsg 			crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
4861099013bSjsg 					     R300_CRTC_MICRO_TILE_BUFFER_DIS |
4871099013bSjsg 					     R300_CRTC_MACRO_TILE_EN);
4881099013bSjsg 		else
4891099013bSjsg 			crtc_offset_cntl |= RADEON_CRTC_TILE_EN;
4901099013bSjsg 	} else {
4911099013bSjsg 		if (ASIC_IS_R300(rdev))
4921099013bSjsg 			crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN |
4931099013bSjsg 					      R300_CRTC_MICRO_TILE_BUFFER_DIS |
4941099013bSjsg 					      R300_CRTC_MACRO_TILE_EN);
4951099013bSjsg 		else
4961099013bSjsg 			crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN;
4971099013bSjsg 	}
4981099013bSjsg 
4991099013bSjsg 	if (tiling_flags & RADEON_TILING_MACRO) {
5001099013bSjsg 		if (ASIC_IS_R300(rdev)) {
5011099013bSjsg 			crtc_tile_x0_y0 = x | (y << 16);
5021099013bSjsg 			base &= ~0x7ff;
5031099013bSjsg 		} else {
5047f4dd379Sjsg 			int byteshift = target_fb->format->cpp[0] * 8 >> 4;
5051099013bSjsg 			int tile_addr = (((y >> 3) * pitch_pixels +  x) >> (8 - byteshift)) << 11;
5061099013bSjsg 			base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
5071099013bSjsg 			crtc_offset_cntl |= (y % 16);
5081099013bSjsg 		}
5091099013bSjsg 	} else {
5101099013bSjsg 		int offset = y * pitch_pixels + x;
5117f4dd379Sjsg 		switch (target_fb->format->cpp[0] * 8) {
5121099013bSjsg 		case 8:
5131099013bSjsg 			offset *= 1;
5141099013bSjsg 			break;
5151099013bSjsg 		case 15:
5161099013bSjsg 		case 16:
5171099013bSjsg 			offset *= 2;
5181099013bSjsg 			break;
5191099013bSjsg 		case 24:
5201099013bSjsg 			offset *= 3;
5211099013bSjsg 			break;
5221099013bSjsg 		case 32:
5231099013bSjsg 			offset *= 4;
5241099013bSjsg 			break;
5251099013bSjsg 		default:
5261099013bSjsg 			return false;
5271099013bSjsg 		}
5281099013bSjsg 		base += offset;
5291099013bSjsg 	}
5301099013bSjsg 
5311099013bSjsg 	base &= ~7;
5321099013bSjsg 
5331099013bSjsg 	if (radeon_crtc->crtc_id == 1)
5341099013bSjsg 		gen_cntl_reg = RADEON_CRTC2_GEN_CNTL;
5351099013bSjsg 	else
5361099013bSjsg 		gen_cntl_reg = RADEON_CRTC_GEN_CNTL;
5371099013bSjsg 
5381099013bSjsg 	gen_cntl_val = RREG32(gen_cntl_reg);
5391099013bSjsg 	gen_cntl_val &= ~(0xf << 8);
5401099013bSjsg 	gen_cntl_val |= (format << 8);
5411099013bSjsg 	gen_cntl_val &= ~RADEON_CRTC_VSTAT_MODE_MASK;
5421099013bSjsg 	WREG32(gen_cntl_reg, gen_cntl_val);
5431099013bSjsg 
5441099013bSjsg 	crtc_offset = (u32)base;
5451099013bSjsg 
5461099013bSjsg 	WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, radeon_crtc->legacy_display_base_addr);
5471099013bSjsg 
5481099013bSjsg 	if (ASIC_IS_R300(rdev)) {
5491099013bSjsg 		if (radeon_crtc->crtc_id)
5501099013bSjsg 			WREG32(R300_CRTC2_TILE_X0_Y0, crtc_tile_x0_y0);
5511099013bSjsg 		else
5521099013bSjsg 			WREG32(R300_CRTC_TILE_X0_Y0, crtc_tile_x0_y0);
5531099013bSjsg 	}
5541099013bSjsg 	WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, crtc_offset_cntl);
5551099013bSjsg 	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
5561099013bSjsg 	WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
5571099013bSjsg 
5583253c27bSkettenis 	if (!atomic && fb && fb != crtc->primary->fb) {
5597f4dd379Sjsg 		rbo = gem_to_radeon_bo(fb->obj[0]);
5601099013bSjsg 		r = radeon_bo_reserve(rbo, false);
5611099013bSjsg 		if (unlikely(r != 0))
5621099013bSjsg 			return r;
5631099013bSjsg 		radeon_bo_unpin(rbo);
5641099013bSjsg 		radeon_bo_unreserve(rbo);
5651099013bSjsg 	}
5661099013bSjsg 
5671099013bSjsg 	/* Bytes per pixel may have changed */
5681099013bSjsg 	radeon_bandwidth_update(rdev);
5691099013bSjsg 
5701099013bSjsg 	return 0;
5711099013bSjsg }
5721099013bSjsg 
radeon_set_crtc_timing(struct drm_crtc * crtc,struct drm_display_mode * mode)5731099013bSjsg static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mode *mode)
5741099013bSjsg {
5751099013bSjsg 	struct drm_device *dev = crtc->dev;
5761099013bSjsg 	struct radeon_device *rdev = dev->dev_private;
5771099013bSjsg 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
5787f4dd379Sjsg 	const struct drm_framebuffer *fb = crtc->primary->fb;
5791099013bSjsg 	struct drm_encoder *encoder;
5801099013bSjsg 	int format;
5811099013bSjsg 	int hsync_start;
5821099013bSjsg 	int hsync_wid;
5831099013bSjsg 	int vsync_wid;
5841099013bSjsg 	uint32_t crtc_h_total_disp;
5851099013bSjsg 	uint32_t crtc_h_sync_strt_wid;
5861099013bSjsg 	uint32_t crtc_v_total_disp;
5871099013bSjsg 	uint32_t crtc_v_sync_strt_wid;
5881099013bSjsg 	bool is_tv = false;
5891099013bSjsg 
5901099013bSjsg 	DRM_DEBUG_KMS("\n");
5911099013bSjsg 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
5921099013bSjsg 		if (encoder->crtc == crtc) {
5931099013bSjsg 			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
5941099013bSjsg 			if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
5951099013bSjsg 				is_tv = true;
5961099013bSjsg 				DRM_INFO("crtc %d is connected to a TV\n", radeon_crtc->crtc_id);
5971099013bSjsg 				break;
5981099013bSjsg 			}
5991099013bSjsg 		}
6001099013bSjsg 	}
6011099013bSjsg 
6027f4dd379Sjsg 	switch (fb->format->cpp[0] * 8) {
6031099013bSjsg 	case 8:
6041099013bSjsg 		format = 2;
6051099013bSjsg 		break;
6061099013bSjsg 	case 15:      /*  555 */
6071099013bSjsg 		format = 3;
6081099013bSjsg 		break;
6091099013bSjsg 	case 16:      /*  565 */
6101099013bSjsg 		format = 4;
6111099013bSjsg 		break;
6121099013bSjsg 	case 24:      /*  RGB */
6131099013bSjsg 		format = 5;
6141099013bSjsg 		break;
6151099013bSjsg 	case 32:      /* xRGB */
6161099013bSjsg 		format = 6;
6171099013bSjsg 		break;
6181099013bSjsg 	default:
6191099013bSjsg 		return false;
6201099013bSjsg 	}
6211099013bSjsg 
6221099013bSjsg 	crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
6231099013bSjsg 			     | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
6241099013bSjsg 
6251099013bSjsg 	hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
6261099013bSjsg 	if (!hsync_wid)
6271099013bSjsg 		hsync_wid = 1;
6281099013bSjsg 	hsync_start = mode->crtc_hsync_start - 8;
6291099013bSjsg 
6301099013bSjsg 	crtc_h_sync_strt_wid = ((hsync_start & 0x1fff)
6311099013bSjsg 				| ((hsync_wid & 0x3f) << 16)
6321099013bSjsg 				| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
6331099013bSjsg 				   ? RADEON_CRTC_H_SYNC_POL
6341099013bSjsg 				   : 0));
6351099013bSjsg 
6361099013bSjsg 	/* This works for double scan mode. */
6371099013bSjsg 	crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
6381099013bSjsg 			     | ((mode->crtc_vdisplay - 1) << 16));
6391099013bSjsg 
6401099013bSjsg 	vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
6411099013bSjsg 	if (!vsync_wid)
6421099013bSjsg 		vsync_wid = 1;
6431099013bSjsg 
6441099013bSjsg 	crtc_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
6451099013bSjsg 				| ((vsync_wid & 0x1f) << 16)
6461099013bSjsg 				| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
6471099013bSjsg 				   ? RADEON_CRTC_V_SYNC_POL
6481099013bSjsg 				   : 0));
6491099013bSjsg 
6501099013bSjsg 	if (radeon_crtc->crtc_id) {
6511099013bSjsg 		uint32_t crtc2_gen_cntl;
6521099013bSjsg 		uint32_t disp2_merge_cntl;
6531099013bSjsg 
6541099013bSjsg 		/* if TV DAC is enabled for another crtc and keep it enabled */
6551099013bSjsg 		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0x00718080;
6561099013bSjsg 		crtc2_gen_cntl |= ((format << 8)
6571099013bSjsg 				   | RADEON_CRTC2_VSYNC_DIS
6581099013bSjsg 				   | RADEON_CRTC2_HSYNC_DIS
6591099013bSjsg 				   | RADEON_CRTC2_DISP_DIS
6601099013bSjsg 				   | RADEON_CRTC2_DISP_REQ_EN_B
6611099013bSjsg 				   | ((mode->flags & DRM_MODE_FLAG_DBLSCAN)
6621099013bSjsg 				      ? RADEON_CRTC2_DBL_SCAN_EN
6631099013bSjsg 				      : 0)
6641099013bSjsg 				   | ((mode->flags & DRM_MODE_FLAG_CSYNC)
6651099013bSjsg 				      ? RADEON_CRTC2_CSYNC_EN
6661099013bSjsg 				      : 0)
6671099013bSjsg 				   | ((mode->flags & DRM_MODE_FLAG_INTERLACE)
6681099013bSjsg 				      ? RADEON_CRTC2_INTERLACE_EN
6691099013bSjsg 				      : 0));
6701099013bSjsg 
6711099013bSjsg 		/* rs4xx chips seem to like to have the crtc enabled when the timing is set */
6721099013bSjsg 		if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480))
6731099013bSjsg 			crtc2_gen_cntl |= RADEON_CRTC2_EN;
6741099013bSjsg 
6751099013bSjsg 		disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
6761099013bSjsg 		disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
6771099013bSjsg 
6781099013bSjsg 		WREG32(RADEON_DISP2_MERGE_CNTL, disp2_merge_cntl);
6791099013bSjsg 		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
6801099013bSjsg 
6811099013bSjsg 		WREG32(RADEON_FP_H2_SYNC_STRT_WID, crtc_h_sync_strt_wid);
6821099013bSjsg 		WREG32(RADEON_FP_V2_SYNC_STRT_WID, crtc_v_sync_strt_wid);
6831099013bSjsg 	} else {
6841099013bSjsg 		uint32_t crtc_gen_cntl;
6851099013bSjsg 		uint32_t crtc_ext_cntl;
6861099013bSjsg 		uint32_t disp_merge_cntl;
6871099013bSjsg 
6881099013bSjsg 		crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0x00718000;
6891099013bSjsg 		crtc_gen_cntl |= (RADEON_CRTC_EXT_DISP_EN
6901099013bSjsg 				 | (format << 8)
6911099013bSjsg 				 | RADEON_CRTC_DISP_REQ_EN_B
6921099013bSjsg 				 | ((mode->flags & DRM_MODE_FLAG_DBLSCAN)
6931099013bSjsg 				    ? RADEON_CRTC_DBL_SCAN_EN
6941099013bSjsg 				    : 0)
6951099013bSjsg 				 | ((mode->flags & DRM_MODE_FLAG_CSYNC)
6961099013bSjsg 				    ? RADEON_CRTC_CSYNC_EN
6971099013bSjsg 				    : 0)
6981099013bSjsg 				 | ((mode->flags & DRM_MODE_FLAG_INTERLACE)
6991099013bSjsg 				    ? RADEON_CRTC_INTERLACE_EN
7001099013bSjsg 				    : 0));
7011099013bSjsg 
7021099013bSjsg 		/* rs4xx chips seem to like to have the crtc enabled when the timing is set */
7031099013bSjsg 		if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480))
7041099013bSjsg 			crtc_gen_cntl |= RADEON_CRTC_EN;
7051099013bSjsg 
7061099013bSjsg 		crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
7071099013bSjsg 		crtc_ext_cntl |= (RADEON_XCRT_CNT_EN |
7081099013bSjsg 				  RADEON_CRTC_VSYNC_DIS |
7091099013bSjsg 				  RADEON_CRTC_HSYNC_DIS |
7101099013bSjsg 				  RADEON_CRTC_DISPLAY_DIS);
7111099013bSjsg 
7121099013bSjsg 		disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
7131099013bSjsg 		disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
7141099013bSjsg 
7151099013bSjsg 		WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
7161099013bSjsg 		WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
7171099013bSjsg 		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
7181099013bSjsg 	}
7191099013bSjsg 
7201099013bSjsg 	if (is_tv)
7211099013bSjsg 		radeon_legacy_tv_adjust_crtc_reg(encoder, &crtc_h_total_disp,
7221099013bSjsg 						 &crtc_h_sync_strt_wid, &crtc_v_total_disp,
7231099013bSjsg 						 &crtc_v_sync_strt_wid);
7241099013bSjsg 
7251099013bSjsg 	WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp);
7261099013bSjsg 	WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid);
7271099013bSjsg 	WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp);
7281099013bSjsg 	WREG32(RADEON_CRTC_V_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_v_sync_strt_wid);
7291099013bSjsg 
7301099013bSjsg 	return true;
7311099013bSjsg }
7321099013bSjsg 
radeon_set_pll(struct drm_crtc * crtc,struct drm_display_mode * mode)7331099013bSjsg static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
7341099013bSjsg {
7351099013bSjsg 	struct drm_device *dev = crtc->dev;
7361099013bSjsg 	struct radeon_device *rdev = dev->dev_private;
7371099013bSjsg 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
7381099013bSjsg 	struct drm_encoder *encoder;
7391099013bSjsg 	uint32_t feedback_div = 0;
7401099013bSjsg 	uint32_t frac_fb_div = 0;
7411099013bSjsg 	uint32_t reference_div = 0;
7421099013bSjsg 	uint32_t post_divider = 0;
7431099013bSjsg 	uint32_t freq = 0;
7441099013bSjsg 	uint8_t pll_gain;
7451099013bSjsg 	bool use_bios_divs = false;
7461099013bSjsg 	/* PLL registers */
7471099013bSjsg 	uint32_t pll_ref_div = 0;
7481099013bSjsg 	uint32_t pll_fb_post_div = 0;
7491099013bSjsg 	uint32_t htotal_cntl = 0;
7501099013bSjsg 	bool is_tv = false;
7511099013bSjsg 	struct radeon_pll *pll;
7521099013bSjsg 
7531099013bSjsg 	struct {
7541099013bSjsg 		int divider;
7551099013bSjsg 		int bitvalue;
7561099013bSjsg 	} *post_div, post_divs[]   = {
7571099013bSjsg 		/* From RAGE 128 VR/RAGE 128 GL Register
7581099013bSjsg 		 * Reference Manual (Technical Reference
7591099013bSjsg 		 * Manual P/N RRG-G04100-C Rev. 0.04), page
7601099013bSjsg 		 * 3-17 (PLL_DIV_[3:0]).
7611099013bSjsg 		 */
7621099013bSjsg 		{  1, 0 },              /* VCLK_SRC                 */
7631099013bSjsg 		{  2, 1 },              /* VCLK_SRC/2               */
7641099013bSjsg 		{  4, 2 },              /* VCLK_SRC/4               */
7651099013bSjsg 		{  8, 3 },              /* VCLK_SRC/8               */
7661099013bSjsg 		{  3, 4 },              /* VCLK_SRC/3               */
7671099013bSjsg 		{ 16, 5 },              /* VCLK_SRC/16              */
7681099013bSjsg 		{  6, 6 },              /* VCLK_SRC/6               */
7691099013bSjsg 		{ 12, 7 },              /* VCLK_SRC/12              */
7701099013bSjsg 		{  0, 0 }
7711099013bSjsg 	};
7721099013bSjsg 
7731099013bSjsg 	if (radeon_crtc->crtc_id)
7741099013bSjsg 		pll = &rdev->clock.p2pll;
7751099013bSjsg 	else
7761099013bSjsg 		pll = &rdev->clock.p1pll;
7771099013bSjsg 
7781099013bSjsg 	pll->flags = RADEON_PLL_LEGACY;
7791099013bSjsg 
7801099013bSjsg 	if (mode->clock > 200000) /* range limits??? */
7811099013bSjsg 		pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
7821099013bSjsg 	else
7831099013bSjsg 		pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
7841099013bSjsg 
7851099013bSjsg 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
7861099013bSjsg 		if (encoder->crtc == crtc) {
7871099013bSjsg 			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
7881099013bSjsg 
7891099013bSjsg 			if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
7901099013bSjsg 				is_tv = true;
7911099013bSjsg 				break;
7921099013bSjsg 			}
7931099013bSjsg 
7941099013bSjsg 			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
7951099013bSjsg 				pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
7961099013bSjsg 			if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
7971099013bSjsg 				if (!rdev->is_atom_bios) {
7981099013bSjsg 					struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
7991099013bSjsg 					struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
8001099013bSjsg 					if (lvds) {
8011099013bSjsg 						if (lvds->use_bios_dividers) {
8021099013bSjsg 							pll_ref_div = lvds->panel_ref_divider;
8031099013bSjsg 							pll_fb_post_div   = (lvds->panel_fb_divider |
8041099013bSjsg 									     (lvds->panel_post_divider << 16));
8051099013bSjsg 							htotal_cntl  = 0;
8061099013bSjsg 							use_bios_divs = true;
8071099013bSjsg 						}
8081099013bSjsg 					}
8091099013bSjsg 				}
8101099013bSjsg 				pll->flags |= RADEON_PLL_USE_REF_DIV;
8111099013bSjsg 			}
8121099013bSjsg 		}
8131099013bSjsg 	}
8141099013bSjsg 
8151099013bSjsg 	DRM_DEBUG_KMS("\n");
8161099013bSjsg 
8171099013bSjsg 	if (!use_bios_divs) {
8181099013bSjsg 		radeon_compute_pll_legacy(pll, mode->clock,
8191099013bSjsg 					  &freq, &feedback_div, &frac_fb_div,
8201099013bSjsg 					  &reference_div, &post_divider);
8211099013bSjsg 
8221099013bSjsg 		for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
8231099013bSjsg 			if (post_div->divider == post_divider)
8241099013bSjsg 				break;
8251099013bSjsg 		}
8261099013bSjsg 
8271099013bSjsg 		if (!post_div->divider)
8281099013bSjsg 			post_div = &post_divs[0];
8291099013bSjsg 
8301099013bSjsg 		DRM_DEBUG_KMS("dc=%u, fd=%d, rd=%d, pd=%d\n",
8311099013bSjsg 			  (unsigned)freq,
8321099013bSjsg 			  feedback_div,
8331099013bSjsg 			  reference_div,
8341099013bSjsg 			  post_divider);
8351099013bSjsg 
8361099013bSjsg 		pll_ref_div   = reference_div;
8371099013bSjsg #if defined(__powerpc__) && (0) /* TODO */
8381099013bSjsg 		/* apparently programming this otherwise causes a hang??? */
8391099013bSjsg 		if (info->MacModel == RADEON_MAC_IBOOK)
8401099013bSjsg 			pll_fb_post_div = 0x000600ad;
8411099013bSjsg 		else
8421099013bSjsg #endif
8431099013bSjsg 			pll_fb_post_div     = (feedback_div | (post_div->bitvalue << 16));
8441099013bSjsg 
8451099013bSjsg 		htotal_cntl    = mode->htotal & 0x7;
8461099013bSjsg 
8471099013bSjsg 	}
8481099013bSjsg 
8491099013bSjsg 	pll_gain = radeon_compute_pll_gain(pll->reference_freq,
8501099013bSjsg 					   pll_ref_div & 0x3ff,
8511099013bSjsg 					   pll_fb_post_div & 0x7ff);
8521099013bSjsg 
8531099013bSjsg 	if (radeon_crtc->crtc_id) {
8541099013bSjsg 		uint32_t pixclks_cntl = ((RREG32_PLL(RADEON_PIXCLKS_CNTL) &
8551099013bSjsg 					  ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
8561099013bSjsg 					 RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
8571099013bSjsg 
8581099013bSjsg 		if (is_tv) {
8591099013bSjsg 			radeon_legacy_tv_adjust_pll2(encoder, &htotal_cntl,
8601099013bSjsg 						     &pll_ref_div, &pll_fb_post_div,
8611099013bSjsg 						     &pixclks_cntl);
8621099013bSjsg 		}
8631099013bSjsg 
8641099013bSjsg 		WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
8651099013bSjsg 			     RADEON_PIX2CLK_SRC_SEL_CPUCLK,
8661099013bSjsg 			     ~(RADEON_PIX2CLK_SRC_SEL_MASK));
8671099013bSjsg 
8681099013bSjsg 		WREG32_PLL_P(RADEON_P2PLL_CNTL,
8691099013bSjsg 			     RADEON_P2PLL_RESET
8701099013bSjsg 			     | RADEON_P2PLL_ATOMIC_UPDATE_EN
8711099013bSjsg 			     | ((uint32_t)pll_gain << RADEON_P2PLL_PVG_SHIFT),
8721099013bSjsg 			     ~(RADEON_P2PLL_RESET
8731099013bSjsg 			       | RADEON_P2PLL_ATOMIC_UPDATE_EN
8741099013bSjsg 			       | RADEON_P2PLL_PVG_MASK));
8751099013bSjsg 
8761099013bSjsg 		WREG32_PLL_P(RADEON_P2PLL_REF_DIV,
8771099013bSjsg 			     pll_ref_div,
8781099013bSjsg 			     ~RADEON_P2PLL_REF_DIV_MASK);
8791099013bSjsg 
8801099013bSjsg 		WREG32_PLL_P(RADEON_P2PLL_DIV_0,
8811099013bSjsg 			     pll_fb_post_div,
8821099013bSjsg 			     ~RADEON_P2PLL_FB0_DIV_MASK);
8831099013bSjsg 
8841099013bSjsg 		WREG32_PLL_P(RADEON_P2PLL_DIV_0,
8851099013bSjsg 			     pll_fb_post_div,
8861099013bSjsg 			     ~RADEON_P2PLL_POST0_DIV_MASK);
8871099013bSjsg 
8881099013bSjsg 		radeon_pll2_write_update(dev);
8891099013bSjsg 		radeon_pll2_wait_for_read_update_complete(dev);
8901099013bSjsg 
8911099013bSjsg 		WREG32_PLL(RADEON_HTOTAL2_CNTL, htotal_cntl);
8921099013bSjsg 
8931099013bSjsg 		WREG32_PLL_P(RADEON_P2PLL_CNTL,
8941099013bSjsg 			     0,
8951099013bSjsg 			     ~(RADEON_P2PLL_RESET
8961099013bSjsg 			       | RADEON_P2PLL_SLEEP
8971099013bSjsg 			       | RADEON_P2PLL_ATOMIC_UPDATE_EN));
8981099013bSjsg 
8991099013bSjsg 		DRM_DEBUG_KMS("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
9001099013bSjsg 			  (unsigned)pll_ref_div,
9011099013bSjsg 			  (unsigned)pll_fb_post_div,
9021099013bSjsg 			  (unsigned)htotal_cntl,
9031099013bSjsg 			  RREG32_PLL(RADEON_P2PLL_CNTL));
9041099013bSjsg 		DRM_DEBUG_KMS("Wrote2: rd=%u, fd=%u, pd=%u\n",
9051099013bSjsg 			  (unsigned)pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
9061099013bSjsg 			  (unsigned)pll_fb_post_div & RADEON_P2PLL_FB0_DIV_MASK,
9071099013bSjsg 			  (unsigned)((pll_fb_post_div &
9081099013bSjsg 				      RADEON_P2PLL_POST0_DIV_MASK) >> 16));
9091099013bSjsg 
9101099013bSjsg 		mdelay(50); /* Let the clock to lock */
9111099013bSjsg 
9121099013bSjsg 		WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
9131099013bSjsg 			     RADEON_PIX2CLK_SRC_SEL_P2PLLCLK,
9141099013bSjsg 			     ~(RADEON_PIX2CLK_SRC_SEL_MASK));
9151099013bSjsg 
9161099013bSjsg 		WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
9171099013bSjsg 	} else {
9181099013bSjsg 		uint32_t pixclks_cntl;
9191099013bSjsg 
9201099013bSjsg 
9211099013bSjsg 		if (is_tv) {
9221099013bSjsg 			pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
9231099013bSjsg 			radeon_legacy_tv_adjust_pll1(encoder, &htotal_cntl, &pll_ref_div,
9241099013bSjsg 						     &pll_fb_post_div, &pixclks_cntl);
9251099013bSjsg 		}
9261099013bSjsg 
9271099013bSjsg 		if (rdev->flags & RADEON_IS_MOBILITY) {
9281099013bSjsg 			/* A temporal workaround for the occasional blanking on certain laptop panels.
9291099013bSjsg 			   This appears to related to the PLL divider registers (fail to lock?).
9301099013bSjsg 			   It occurs even when all dividers are the same with their old settings.
9311099013bSjsg 			   In this case we really don't need to fiddle with PLL registers.
9321099013bSjsg 			   By doing this we can avoid the blanking problem with some panels.
9331099013bSjsg 			*/
9341099013bSjsg 			if ((pll_ref_div == (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) &&
9351099013bSjsg 			    (pll_fb_post_div == (RREG32_PLL(RADEON_PPLL_DIV_3) &
9361099013bSjsg 						 (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) {
9371099013bSjsg 				WREG32_P(RADEON_CLOCK_CNTL_INDEX,
9381099013bSjsg 					 RADEON_PLL_DIV_SEL,
9391099013bSjsg 					 ~(RADEON_PLL_DIV_SEL));
9401099013bSjsg 				r100_pll_errata_after_index(rdev);
9411099013bSjsg 				return;
9421099013bSjsg 			}
9431099013bSjsg 		}
9441099013bSjsg 
9451099013bSjsg 		WREG32_PLL_P(RADEON_VCLK_ECP_CNTL,
9461099013bSjsg 			     RADEON_VCLK_SRC_SEL_CPUCLK,
9471099013bSjsg 			     ~(RADEON_VCLK_SRC_SEL_MASK));
9481099013bSjsg 		WREG32_PLL_P(RADEON_PPLL_CNTL,
9491099013bSjsg 			     RADEON_PPLL_RESET
9501099013bSjsg 			     | RADEON_PPLL_ATOMIC_UPDATE_EN
9511099013bSjsg 			     | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
9521099013bSjsg 			     | ((uint32_t)pll_gain << RADEON_PPLL_PVG_SHIFT),
9531099013bSjsg 			     ~(RADEON_PPLL_RESET
9541099013bSjsg 			       | RADEON_PPLL_ATOMIC_UPDATE_EN
9551099013bSjsg 			       | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
9561099013bSjsg 			       | RADEON_PPLL_PVG_MASK));
9571099013bSjsg 
9581099013bSjsg 		WREG32_P(RADEON_CLOCK_CNTL_INDEX,
9591099013bSjsg 			 RADEON_PLL_DIV_SEL,
9601099013bSjsg 			 ~(RADEON_PLL_DIV_SEL));
9611099013bSjsg 		r100_pll_errata_after_index(rdev);
9621099013bSjsg 
9631099013bSjsg 		if (ASIC_IS_R300(rdev) ||
9641099013bSjsg 		    (rdev->family == CHIP_RS300) ||
9651099013bSjsg 		    (rdev->family == CHIP_RS400) ||
9661099013bSjsg 		    (rdev->family == CHIP_RS480)) {
9671099013bSjsg 			if (pll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
9681099013bSjsg 				/* When restoring console mode, use saved PPLL_REF_DIV
9691099013bSjsg 				 * setting.
9701099013bSjsg 				 */
9711099013bSjsg 				WREG32_PLL_P(RADEON_PPLL_REF_DIV,
9721099013bSjsg 					     pll_ref_div,
9731099013bSjsg 					     0);
9741099013bSjsg 			} else {
9751099013bSjsg 				/* R300 uses ref_div_acc field as real ref divider */
9761099013bSjsg 				WREG32_PLL_P(RADEON_PPLL_REF_DIV,
9771099013bSjsg 					     (pll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
9781099013bSjsg 					     ~R300_PPLL_REF_DIV_ACC_MASK);
9791099013bSjsg 			}
9801099013bSjsg 		} else
9811099013bSjsg 			WREG32_PLL_P(RADEON_PPLL_REF_DIV,
9821099013bSjsg 				     pll_ref_div,
9831099013bSjsg 				     ~RADEON_PPLL_REF_DIV_MASK);
9841099013bSjsg 
9851099013bSjsg 		WREG32_PLL_P(RADEON_PPLL_DIV_3,
9861099013bSjsg 			     pll_fb_post_div,
9871099013bSjsg 			     ~RADEON_PPLL_FB3_DIV_MASK);
9881099013bSjsg 
9891099013bSjsg 		WREG32_PLL_P(RADEON_PPLL_DIV_3,
9901099013bSjsg 			     pll_fb_post_div,
9911099013bSjsg 			     ~RADEON_PPLL_POST3_DIV_MASK);
9921099013bSjsg 
9931099013bSjsg 		radeon_pll_write_update(dev);
9941099013bSjsg 		radeon_pll_wait_for_read_update_complete(dev);
9951099013bSjsg 
9961099013bSjsg 		WREG32_PLL(RADEON_HTOTAL_CNTL, htotal_cntl);
9971099013bSjsg 
9981099013bSjsg 		WREG32_PLL_P(RADEON_PPLL_CNTL,
9991099013bSjsg 			     0,
10001099013bSjsg 			     ~(RADEON_PPLL_RESET
10011099013bSjsg 			       | RADEON_PPLL_SLEEP
10021099013bSjsg 			       | RADEON_PPLL_ATOMIC_UPDATE_EN
10031099013bSjsg 			       | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN));
10041099013bSjsg 
10051099013bSjsg 		DRM_DEBUG_KMS("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
10061099013bSjsg 			  pll_ref_div,
10071099013bSjsg 			  pll_fb_post_div,
10081099013bSjsg 			  (unsigned)htotal_cntl,
10091099013bSjsg 			  RREG32_PLL(RADEON_PPLL_CNTL));
10101099013bSjsg 		DRM_DEBUG_KMS("Wrote: rd=%d, fd=%d, pd=%d\n",
10111099013bSjsg 			  pll_ref_div & RADEON_PPLL_REF_DIV_MASK,
10121099013bSjsg 			  pll_fb_post_div & RADEON_PPLL_FB3_DIV_MASK,
10131099013bSjsg 			  (pll_fb_post_div & RADEON_PPLL_POST3_DIV_MASK) >> 16);
10141099013bSjsg 
10151099013bSjsg 		mdelay(50); /* Let the clock to lock */
10161099013bSjsg 
10171099013bSjsg 		WREG32_PLL_P(RADEON_VCLK_ECP_CNTL,
10181099013bSjsg 			     RADEON_VCLK_SRC_SEL_PPLLCLK,
10191099013bSjsg 			     ~(RADEON_VCLK_SRC_SEL_MASK));
10201099013bSjsg 
10211099013bSjsg 		if (is_tv)
10221099013bSjsg 			WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
10231099013bSjsg 	}
10241099013bSjsg }
10251099013bSjsg 
radeon_crtc_mode_fixup(struct drm_crtc * crtc,const struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)10261099013bSjsg static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc,
10271099013bSjsg 				   const struct drm_display_mode *mode,
10281099013bSjsg 				   struct drm_display_mode *adjusted_mode)
10291099013bSjsg {
10301099013bSjsg 	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
10311099013bSjsg 		return false;
10321099013bSjsg 	return true;
10331099013bSjsg }
10341099013bSjsg 
radeon_crtc_mode_set(struct drm_crtc * crtc,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode,int x,int y,struct drm_framebuffer * old_fb)10351099013bSjsg static int radeon_crtc_mode_set(struct drm_crtc *crtc,
10361099013bSjsg 				 struct drm_display_mode *mode,
10371099013bSjsg 				 struct drm_display_mode *adjusted_mode,
10381099013bSjsg 				 int x, int y, struct drm_framebuffer *old_fb)
10391099013bSjsg {
10401099013bSjsg 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
10411099013bSjsg 
10421099013bSjsg 	/* TODO TV */
10431099013bSjsg 	radeon_crtc_set_base(crtc, x, y, old_fb);
10441099013bSjsg 	radeon_set_crtc_timing(crtc, adjusted_mode);
10451099013bSjsg 	radeon_set_pll(crtc, adjusted_mode);
10461099013bSjsg 	radeon_overscan_setup(crtc, adjusted_mode);
10471099013bSjsg 	if (radeon_crtc->crtc_id == 0) {
10481099013bSjsg 		radeon_legacy_rmx_mode_set(crtc, adjusted_mode);
10491099013bSjsg 	} else {
10501099013bSjsg 		if (radeon_crtc->rmx_type != RMX_OFF) {
10511099013bSjsg 			/* FIXME: only first crtc has rmx what should we
10521099013bSjsg 			 * do ?
10531099013bSjsg 			 */
10541099013bSjsg 			DRM_ERROR("Mode need scaling but only first crtc can do that.\n");
10551099013bSjsg 		}
10561099013bSjsg 	}
10577ccd5a2cSjsg 	radeon_cursor_reset(crtc);
10581099013bSjsg 	return 0;
10591099013bSjsg }
10601099013bSjsg 
radeon_crtc_prepare(struct drm_crtc * crtc)10611099013bSjsg static void radeon_crtc_prepare(struct drm_crtc *crtc)
10621099013bSjsg {
10631099013bSjsg 	struct drm_device *dev = crtc->dev;
10641099013bSjsg 	struct drm_crtc *crtci;
10651099013bSjsg 
10661099013bSjsg 	/*
10671099013bSjsg 	* The hardware wedges sometimes if you reconfigure one CRTC
10681099013bSjsg 	* whilst another is running (see fdo bug #24611).
10691099013bSjsg 	*/
10701099013bSjsg 	list_for_each_entry(crtci, &dev->mode_config.crtc_list, head)
10711099013bSjsg 		radeon_crtc_dpms(crtci, DRM_MODE_DPMS_OFF);
10721099013bSjsg }
10731099013bSjsg 
radeon_crtc_commit(struct drm_crtc * crtc)10741099013bSjsg static void radeon_crtc_commit(struct drm_crtc *crtc)
10751099013bSjsg {
10761099013bSjsg 	struct drm_device *dev = crtc->dev;
10771099013bSjsg 	struct drm_crtc *crtci;
10781099013bSjsg 
10791099013bSjsg 	/*
10801099013bSjsg 	* Reenable the CRTCs that should be running.
10811099013bSjsg 	*/
10821099013bSjsg 	list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) {
10831099013bSjsg 		if (crtci->enabled)
10841099013bSjsg 			radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
10851099013bSjsg 	}
10867ccd5a2cSjsg }
10877ccd5a2cSjsg 
radeon_crtc_disable(struct drm_crtc * crtc)10887ccd5a2cSjsg static void radeon_crtc_disable(struct drm_crtc *crtc)
10897ccd5a2cSjsg {
10907ccd5a2cSjsg 	radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
10917ccd5a2cSjsg 	if (crtc->primary->fb) {
10927ccd5a2cSjsg 		int r;
10937ccd5a2cSjsg 		struct radeon_bo *rbo;
10947ccd5a2cSjsg 
10957f4dd379Sjsg 		rbo = gem_to_radeon_bo(crtc->primary->fb->obj[0]);
10967ccd5a2cSjsg 		r = radeon_bo_reserve(rbo, false);
10977ccd5a2cSjsg 		if (unlikely(r))
10987ccd5a2cSjsg 			DRM_ERROR("failed to reserve rbo before unpin\n");
10997ccd5a2cSjsg 		else {
11007ccd5a2cSjsg 			radeon_bo_unpin(rbo);
11017ccd5a2cSjsg 			radeon_bo_unreserve(rbo);
11027ccd5a2cSjsg 		}
11037ccd5a2cSjsg 	}
11041099013bSjsg }
11051099013bSjsg 
11061099013bSjsg static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
11071099013bSjsg 	.dpms = radeon_crtc_dpms,
11081099013bSjsg 	.mode_fixup = radeon_crtc_mode_fixup,
11091099013bSjsg 	.mode_set = radeon_crtc_mode_set,
11101099013bSjsg 	.mode_set_base = radeon_crtc_set_base,
11111099013bSjsg 	.mode_set_base_atomic = radeon_crtc_set_base_atomic,
11121099013bSjsg 	.prepare = radeon_crtc_prepare,
11131099013bSjsg 	.commit = radeon_crtc_commit,
1114c349dbc7Sjsg 	.disable = radeon_crtc_disable,
1115c349dbc7Sjsg 	.get_scanout_position = radeon_get_crtc_scanout_position,
11161099013bSjsg };
11171099013bSjsg 
11181099013bSjsg 
radeon_legacy_init_crtc(struct drm_device * dev,struct radeon_crtc * radeon_crtc)11191099013bSjsg void radeon_legacy_init_crtc(struct drm_device *dev,
11201099013bSjsg 			       struct radeon_crtc *radeon_crtc)
11211099013bSjsg {
11221099013bSjsg 	if (radeon_crtc->crtc_id == 1)
11231099013bSjsg 		radeon_crtc->crtc_offset = RADEON_CRTC2_H_TOTAL_DISP - RADEON_CRTC_H_TOTAL_DISP;
11241099013bSjsg 	drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs);
11251099013bSjsg }
1126