radeondrm

make radeondrm(1) work with iMac 11,1
Log | Files | Refs | README

imac_11_1_radeondrm.diff (11913B)


      1 Index: radeon/atombios_encoders.c
      2 ===================================================================
      3 RCS file: /cvs/src/sys/dev/pci/drm/radeon/atombios_encoders.c,v
      4 retrieving revision 1.17
      5 diff -u -p -r1.17 atombios_encoders.c
      6 --- radeon/atombios_encoders.c	24 Feb 2022 12:49:47 -0000	1.17
      7 +++ radeon/atombios_encoders.c	23 Jan 2023 00:24:52 -0000
      8 @@ -202,6 +202,9 @@ void radeon_atom_backlight_init(struct r
      9  	    !dmi_match(DMI_PRODUCT_NAME, "iMac12,1"))
     10  		return;
     11  
     12 +	if (dmi_match(DMI_PRODUCT_NAME, "iMac11,1"))
     13 +		return;
     14 +
     15  	if (!radeon_encoder->enc_priv)
     16  		return;
     17  
     18 @@ -2187,12 +2190,13 @@ int radeon_atom_pick_dig_encoder(struct 
     19  	}
     20  
     21  	/*
     22 -	 * On DCE32 any encoder can drive any block so usually just use crtc id,
     23 -	 * but Apple thinks different at least on iMac10,1, so there use linkb,
     24 -	 * otherwise the internal eDP panel will stay dark.
     25 +	 * On DCE31 any encoder can drive any block so usually just use crtc id,
     26 +	 * but Apple thinks different at least on iMac10,1 and iMac11,1, so
     27 +	 * there use linkb, otherwise the internal eDP panel will stay dark.
     28  	 */
     29 -	if (ASIC_IS_DCE32(rdev)) {
     30 -		if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1"))
     31 +	if (ASIC_IS_DCE31(rdev)) {
     32 +		if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1") ||
     33 +		    dmi_match(DMI_PRODUCT_NAME, "iMac11,1"))
     34  			enc_idx = (dig->linkb) ? 1 : 0;
     35  		else
     36  			enc_idx = radeon_crtc->crtc_id;
     37 Index: radeon/radeon.h
     38 ===================================================================
     39 RCS file: /cvs/src/sys/dev/pci/drm/radeon/radeon.h,v
     40 retrieving revision 1.27
     41 diff -u -p -r1.27 radeon.h
     42 --- radeon/radeon.h	14 Jan 2022 06:53:15 -0000	1.27
     43 +++ radeon/radeon.h	23 Jan 2023 00:24:52 -0000
     44 @@ -2711,6 +2711,7 @@ void r100_pll_errata_after_index(struct 
     45  			    (rdev->family == CHIP_RS740)  ||	\
     46  			    (rdev->family >= CHIP_R600))
     47  #define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620))
     48 +#define ASIC_IS_DCE31(rdev) ((rdev->family >= CHIP_RV770))
     49  #define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730))
     50  #define ASIC_IS_DCE4(rdev) ((rdev->family >= CHIP_CEDAR))
     51  #define ASIC_IS_DCE41(rdev) ((rdev->family >= CHIP_PALM) && \
     52 Index: radeon/radeon_display.c
     53 ===================================================================
     54 RCS file: /cvs/src/sys/dev/pci/drm/radeon/radeon_display.c,v
     55 retrieving revision 1.24
     56 diff -u -p -r1.24 radeon_display.c
     57 --- radeon/radeon_display.c	14 Jan 2022 06:53:15 -0000	1.24
     58 +++ radeon/radeon_display.c	23 Jan 2023 00:24:52 -0000
     59 @@ -864,76 +864,66 @@ static bool radeon_setup_enc_conn(struct
     60  }
     61  
     62  /* avivo */
     63 +static void avivo_get_fb_div(struct radeon_pll *pll,
     64 +			     u32 target_clock,
     65 +			     u32 post_div,
     66 +			     u32 ref_div,
     67 +			     u32 *fb_div,
     68 +			     u32 *frac_fb_div)
     69 +{
     70 +	u32 tmp = post_div * ref_div;
     71  
     72 -/**
     73 - * avivo_reduce_ratio - fractional number reduction
     74 - *
     75 - * @nom: nominator
     76 - * @den: denominator
     77 - * @nom_min: minimum value for nominator
     78 - * @den_min: minimum value for denominator
     79 - *
     80 - * Find the greatest common divisor and apply it on both nominator and
     81 - * denominator, but make nominator and denominator are at least as large
     82 - * as their minimum values.
     83 - */
     84 -static void avivo_reduce_ratio(unsigned *nom, unsigned *den,
     85 -			       unsigned nom_min, unsigned den_min)
     86 +	tmp *= target_clock;
     87 +	*fb_div = tmp / pll->reference_freq;
     88 +	*frac_fb_div = tmp % pll->reference_freq;
     89 +
     90 +        if (*fb_div > pll->max_feedback_div)
     91 +		*fb_div = pll->max_feedback_div;
     92 +        else if (*fb_div < pll->min_feedback_div)
     93 +                *fb_div = pll->min_feedback_div;
     94 +}
     95 +
     96 +static u32 avivo_get_post_div(struct radeon_pll *pll,
     97 +			      u32 target_clock)
     98  {
     99 -	unsigned tmp;
    100 +	u32 vco, post_div, tmp;
    101  
    102 -	/* reduce the numbers to a simpler ratio */
    103 -	tmp = gcd(*nom, *den);
    104 -	*nom /= tmp;
    105 -	*den /= tmp;
    106 -
    107 -	/* make sure nominator is large enough */
    108 -	if (*nom < nom_min) {
    109 -		tmp = DIV_ROUND_UP(nom_min, *nom);
    110 -		*nom *= tmp;
    111 -		*den *= tmp;
    112 +	if (pll->flags & RADEON_PLL_USE_POST_DIV)
    113 +		return pll->post_div;
    114 +
    115 +	if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) {
    116 +		if (pll->flags & RADEON_PLL_IS_LCD)
    117 +			vco = pll->lcd_pll_out_min;
    118 +		else
    119 +			vco = pll->pll_out_min;
    120 +	} else {
    121 +		if (pll->flags & RADEON_PLL_IS_LCD)
    122 +			vco = pll->lcd_pll_out_max;
    123 +		else
    124 +			vco = pll->pll_out_max;
    125  	}
    126  
    127 -	/* make sure the denominator is large enough */
    128 -	if (*den < den_min) {
    129 -		tmp = DIV_ROUND_UP(den_min, *den);
    130 -		*nom *= tmp;
    131 -		*den *= tmp;
    132 +	post_div = vco / target_clock;
    133 +	tmp = vco % target_clock;
    134 +
    135 +	if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) {
    136 +		if (tmp)
    137 +			post_div++;
    138 +	} else {
    139 +		if (!tmp)
    140 +			post_div--;
    141  	}
    142 -}
    143  
    144 -/**
    145 - * avivo_get_fb_ref_div - feedback and ref divider calculation
    146 - *
    147 - * @nom: nominator
    148 - * @den: denominator
    149 - * @post_div: post divider
    150 - * @fb_div_max: feedback divider maximum
    151 - * @ref_div_max: reference divider maximum
    152 - * @fb_div: resulting feedback divider
    153 - * @ref_div: resulting reference divider
    154 - *
    155 - * Calculate feedback and reference divider for a given post divider. Makes
    156 - * sure we stay within the limits.
    157 - */
    158 -static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div,
    159 -				 unsigned fb_div_max, unsigned ref_div_max,
    160 -				 unsigned *fb_div, unsigned *ref_div)
    161 -{
    162 -	/* limit reference * post divider to a maximum */
    163 -	ref_div_max = max(min(100 / post_div, ref_div_max), 1u);
    164 +	if (post_div > pll->max_post_div)
    165 +		post_div = pll->max_post_div;
    166 +	else if (post_div < pll->min_post_div)
    167 +		post_div = pll->min_post_div;
    168  
    169 -	/* get matching reference and feedback divider */
    170 -	*ref_div = min(max(den/post_div, 1u), ref_div_max);
    171 -	*fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den);
    172 -
    173 -	/* limit fb divider to its maximum */
    174 -	if (*fb_div > fb_div_max) {
    175 -		*ref_div = (*ref_div * fb_div_max)/(*fb_div);
    176 -		*fb_div = fb_div_max;
    177 -	}
    178 +	return post_div;
    179  }
    180  
    181 +#define MAX_TOLERANCE 10
    182 +
    183  /**
    184   * radeon_compute_pll_avivo - compute PLL paramaters
    185   *
    186 @@ -956,138 +946,55 @@ void radeon_compute_pll_avivo(struct rad
    187  			      u32 *ref_div_p,
    188  			      u32 *post_div_p)
    189  {
    190 -	unsigned target_clock = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ?
    191 -		freq : freq / 10;
    192 -
    193 -	unsigned fb_div_min, fb_div_max, fb_div;
    194 -	unsigned post_div_min, post_div_max, post_div;
    195 -	unsigned ref_div_min, ref_div_max, ref_div;
    196 -	unsigned post_div_best, diff_best;
    197 -	unsigned nom, den;
    198 -
    199 -	/* determine allowed feedback divider range */
    200 -	fb_div_min = pll->min_feedback_div;
    201 -	fb_div_max = pll->max_feedback_div;
    202 -
    203 -	if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
    204 -		fb_div_min *= 10;
    205 -		fb_div_max *= 10;
    206 -	}
    207 +       u32 target_clock = freq / 10;
    208 +       u32 post_div = avivo_get_post_div(pll, target_clock);
    209 +       u32 ref_div = pll->min_ref_div;
    210 +       u32 fb_div = 0, frac_fb_div = 0, tmp;
    211  
    212 -	/* determine allowed ref divider range */
    213  	if (pll->flags & RADEON_PLL_USE_REF_DIV)
    214 -		ref_div_min = pll->reference_div;
    215 -	else
    216 -		ref_div_min = pll->min_ref_div;
    217 -
    218 -	if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV &&
    219 -	    pll->flags & RADEON_PLL_USE_REF_DIV)
    220 -		ref_div_max = pll->reference_div;
    221 -	else if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP)
    222 -		/* fix for problems on RS880 */
    223 -		ref_div_max = min(pll->max_ref_div, 7u);
    224 -	else
    225 -		ref_div_max = pll->max_ref_div;
    226 -
    227 -	/* determine allowed post divider range */
    228 -	if (pll->flags & RADEON_PLL_USE_POST_DIV) {
    229 -		post_div_min = pll->post_div;
    230 -		post_div_max = pll->post_div;
    231 -	} else {
    232 -		unsigned vco_min, vco_max;
    233 +               ref_div = pll->reference_div;
    234  
    235 -		if (pll->flags & RADEON_PLL_IS_LCD) {
    236 -			vco_min = pll->lcd_pll_out_min;
    237 -			vco_max = pll->lcd_pll_out_max;
    238 -		} else {
    239 -			vco_min = pll->pll_out_min;
    240 -			vco_max = pll->pll_out_max;
    241 +       if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
    242 +               avivo_get_fb_div(pll, target_clock, post_div, ref_div, &fb_div,
    243 + &frac_fb_div);
    244 +               frac_fb_div = (100 * frac_fb_div) / pll->reference_freq;
    245 +               if (frac_fb_div >= 5) {
    246 +                       frac_fb_div -= 5;
    247 +                       frac_fb_div = frac_fb_div / 10;
    248 +                       frac_fb_div++;
    249  		}
    250  
    251 -		if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
    252 -			vco_min *= 10;
    253 -			vco_max *= 10;
    254 +               if (frac_fb_div >= 10) {
    255 +                       fb_div++;
    256 +                       frac_fb_div = 0;
    257  		}
    258 -
    259 -		post_div_min = vco_min / target_clock;
    260 -		if ((target_clock * post_div_min) < vco_min)
    261 -			++post_div_min;
    262 -		if (post_div_min < pll->min_post_div)
    263 -			post_div_min = pll->min_post_div;
    264 -
    265 -		post_div_max = vco_max / target_clock;
    266 -		if ((target_clock * post_div_max) > vco_max)
    267 -			--post_div_max;
    268 -		if (post_div_max > pll->max_post_div)
    269 -			post_div_max = pll->max_post_div;
    270 -	}
    271 -
    272 -	/* represent the searched ratio as fractional number */
    273 -	nom = target_clock;
    274 -	den = pll->reference_freq;
    275 -
    276 -	/* reduce the numbers to a simpler ratio */
    277 -	avivo_reduce_ratio(&nom, &den, fb_div_min, post_div_min);
    278 -
    279 -	/* now search for a post divider */
    280 -	if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP)
    281 -		post_div_best = post_div_min;
    282 -	else
    283 -		post_div_best = post_div_max;
    284 -	diff_best = ~0;
    285 -
    286 -	for (post_div = post_div_min; post_div <= post_div_max; ++post_div) {
    287 -		unsigned diff;
    288 -		avivo_get_fb_ref_div(nom, den, post_div, fb_div_max,
    289 -				     ref_div_max, &fb_div, &ref_div);
    290 -		diff = abs(target_clock - (pll->reference_freq * fb_div) /
    291 -			(ref_div * post_div));
    292 -
    293 -		if (diff < diff_best || (diff == diff_best &&
    294 -		    !(pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP))) {
    295 -
    296 -			post_div_best = post_div;
    297 -			diff_best = diff;
    298 -		}
    299 -	}
    300 -	post_div = post_div_best;
    301 -
    302 -	/* get the feedback and reference divider for the optimal value */
    303 -	avivo_get_fb_ref_div(nom, den, post_div, fb_div_max, ref_div_max,
    304 -			     &fb_div, &ref_div);
    305 -
    306 -	/* reduce the numbers to a simpler ratio once more */
    307 -	/* this also makes sure that the reference divider is large enough */
    308 -	avivo_reduce_ratio(&fb_div, &ref_div, fb_div_min, ref_div_min);
    309 -
    310 -	/* avoid high jitter with small fractional dividers */
    311 -	if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && (fb_div % 10)) {
    312 -		fb_div_min = max(fb_div_min, (9 - (fb_div % 10)) * 20 + 50);
    313 -		if (fb_div < fb_div_min) {
    314 -			unsigned tmp = DIV_ROUND_UP(fb_div_min, fb_div);
    315 -			fb_div *= tmp;
    316 -			ref_div *= tmp;
    317 -		}
    318 -	}
    319 -
    320 -	/* and finally save the result */
    321 -	if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
    322 -		*fb_div_p = fb_div / 10;
    323 -		*frac_fb_div_p = fb_div % 10;
    324  	} else {
    325 -		*fb_div_p = fb_div;
    326 -		*frac_fb_div_p = 0;
    327 -	}
    328 -
    329 -	*dot_clock_p = ((pll->reference_freq * *fb_div_p * 10) +
    330 -			(pll->reference_freq * *frac_fb_div_p)) /
    331 -		       (ref_div * post_div * 10);
    332 +               while (ref_div <= pll->max_ref_div) {
    333 +                       avivo_get_fb_div(pll, target_clock, post_div, ref_div,
    334 +                                        &fb_div, &frac_fb_div);
    335 +                       if (frac_fb_div >= (pll->reference_freq / 2))
    336 +                               fb_div++;
    337 +                       frac_fb_div = 0;
    338 +                       tmp = (pll->reference_freq * fb_div) / (post_div * ref_div);
    339 +                       tmp = (tmp * 10000) / target_clock;
    340 +
    341 +                       if (tmp > (10000 + MAX_TOLERANCE))
    342 +                               ref_div++;
    343 +                       else if (tmp >= (10000 - MAX_TOLERANCE))
    344 +                               break;
    345 +                       else
    346 +                               ref_div++;
    347 +               }
    348 +	}
    349 +
    350 +       *dot_clock_p = ((pll->reference_freq * fb_div * 10) + (pll->reference_freq * frac_fb_div)) / (ref_div * post_div * 10);
    351 +       *fb_div_p = fb_div;
    352 +       *frac_fb_div_p = frac_fb_div;
    353  	*ref_div_p = ref_div;
    354  	*post_div_p = post_div;
    355  
    356 -	DRM_DEBUG_KMS("%d - %d, pll dividers - fb: %d.%d ref: %d, post %d\n",
    357 -		      freq, *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p,
    358 -		      ref_div, post_div);
    359 +       DRM_DEBUG_KMS("%d, pll dividers - fb: %d.%d ref: %d, post %d\n",
    360 +                     *dot_clock_p, fb_div, frac_fb_div, ref_div, post_div);
    361  }
    362  
    363  /* pre-avivo */