linux/drivers/gpu/drm/radeon/radeon_display.c
<<
>>
Prefs
   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 "radeon_drm.h"
  28#include "radeon.h"
  29
  30#include "atom.h"
  31#include <asm/div64.h>
  32
  33#include "drm_crtc_helper.h"
  34#include "drm_edid.h"
  35
  36static int radeon_ddc_dump(struct drm_connector *connector);
  37
  38static void avivo_crtc_load_lut(struct drm_crtc *crtc)
  39{
  40        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  41        struct drm_device *dev = crtc->dev;
  42        struct radeon_device *rdev = dev->dev_private;
  43        int i;
  44
  45        DRM_DEBUG("%d\n", radeon_crtc->crtc_id);
  46        WREG32(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0);
  47
  48        WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
  49        WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
  50        WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
  51
  52        WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff);
  53        WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff);
  54        WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff);
  55
  56        WREG32(AVIVO_DC_LUT_RW_SELECT, radeon_crtc->crtc_id);
  57        WREG32(AVIVO_DC_LUT_RW_MODE, 0);
  58        WREG32(AVIVO_DC_LUT_WRITE_EN_MASK, 0x0000003f);
  59
  60        WREG8(AVIVO_DC_LUT_RW_INDEX, 0);
  61        for (i = 0; i < 256; i++) {
  62                WREG32(AVIVO_DC_LUT_30_COLOR,
  63                             (radeon_crtc->lut_r[i] << 20) |
  64                             (radeon_crtc->lut_g[i] << 10) |
  65                             (radeon_crtc->lut_b[i] << 0));
  66        }
  67
  68        WREG32(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id);
  69}
  70
  71static void legacy_crtc_load_lut(struct drm_crtc *crtc)
  72{
  73        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  74        struct drm_device *dev = crtc->dev;
  75        struct radeon_device *rdev = dev->dev_private;
  76        int i;
  77        uint32_t dac2_cntl;
  78
  79        dac2_cntl = RREG32(RADEON_DAC_CNTL2);
  80        if (radeon_crtc->crtc_id == 0)
  81                dac2_cntl &= (uint32_t)~RADEON_DAC2_PALETTE_ACC_CTL;
  82        else
  83                dac2_cntl |= RADEON_DAC2_PALETTE_ACC_CTL;
  84        WREG32(RADEON_DAC_CNTL2, dac2_cntl);
  85
  86        WREG8(RADEON_PALETTE_INDEX, 0);
  87        for (i = 0; i < 256; i++) {
  88                WREG32(RADEON_PALETTE_30_DATA,
  89                             (radeon_crtc->lut_r[i] << 20) |
  90                             (radeon_crtc->lut_g[i] << 10) |
  91                             (radeon_crtc->lut_b[i] << 0));
  92        }
  93}
  94
  95void radeon_crtc_load_lut(struct drm_crtc *crtc)
  96{
  97        struct drm_device *dev = crtc->dev;
  98        struct radeon_device *rdev = dev->dev_private;
  99
 100        if (!crtc->enabled)
 101                return;
 102
 103        if (ASIC_IS_AVIVO(rdev))
 104                avivo_crtc_load_lut(crtc);
 105        else
 106                legacy_crtc_load_lut(crtc);
 107}
 108
 109/** Sets the color ramps on behalf of fbcon */
 110void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
 111                              u16 blue, int regno)
 112{
 113        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 114
 115        radeon_crtc->lut_r[regno] = red >> 6;
 116        radeon_crtc->lut_g[regno] = green >> 6;
 117        radeon_crtc->lut_b[regno] = blue >> 6;
 118}
 119
 120/** Gets the color ramps on behalf of fbcon */
 121void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
 122                              u16 *blue, int regno)
 123{
 124        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 125
 126        *red = radeon_crtc->lut_r[regno] << 6;
 127        *green = radeon_crtc->lut_g[regno] << 6;
 128        *blue = radeon_crtc->lut_b[regno] << 6;
 129}
 130
 131static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
 132                                  u16 *blue, uint32_t size)
 133{
 134        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 135        int i;
 136
 137        if (size != 256) {
 138                return;
 139        }
 140
 141        /* userspace palettes are always correct as is */
 142        for (i = 0; i < 256; i++) {
 143                radeon_crtc->lut_r[i] = red[i] >> 6;
 144                radeon_crtc->lut_g[i] = green[i] >> 6;
 145                radeon_crtc->lut_b[i] = blue[i] >> 6;
 146        }
 147        radeon_crtc_load_lut(crtc);
 148}
 149
 150static void radeon_crtc_destroy(struct drm_crtc *crtc)
 151{
 152        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 153
 154        drm_crtc_cleanup(crtc);
 155        kfree(radeon_crtc);
 156}
 157
 158static const struct drm_crtc_funcs radeon_crtc_funcs = {
 159        .cursor_set = radeon_crtc_cursor_set,
 160        .cursor_move = radeon_crtc_cursor_move,
 161        .gamma_set = radeon_crtc_gamma_set,
 162        .set_config = drm_crtc_helper_set_config,
 163        .destroy = radeon_crtc_destroy,
 164};
 165
 166static void radeon_crtc_init(struct drm_device *dev, int index)
 167{
 168        struct radeon_device *rdev = dev->dev_private;
 169        struct radeon_crtc *radeon_crtc;
 170        int i;
 171
 172        radeon_crtc = kzalloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
 173        if (radeon_crtc == NULL)
 174                return;
 175
 176        drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs);
 177
 178        drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
 179        radeon_crtc->crtc_id = index;
 180        rdev->mode_info.crtcs[index] = radeon_crtc;
 181
 182#if 0
 183        radeon_crtc->mode_set.crtc = &radeon_crtc->base;
 184        radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1);
 185        radeon_crtc->mode_set.num_connectors = 0;
 186#endif
 187
 188        for (i = 0; i < 256; i++) {
 189                radeon_crtc->lut_r[i] = i << 2;
 190                radeon_crtc->lut_g[i] = i << 2;
 191                radeon_crtc->lut_b[i] = i << 2;
 192        }
 193
 194        if (rdev->is_atom_bios && (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom))
 195                radeon_atombios_init_crtc(dev, radeon_crtc);
 196        else
 197                radeon_legacy_init_crtc(dev, radeon_crtc);
 198}
 199
 200static const char *encoder_names[34] = {
 201        "NONE",
 202        "INTERNAL_LVDS",
 203        "INTERNAL_TMDS1",
 204        "INTERNAL_TMDS2",
 205        "INTERNAL_DAC1",
 206        "INTERNAL_DAC2",
 207        "INTERNAL_SDVOA",
 208        "INTERNAL_SDVOB",
 209        "SI170B",
 210        "CH7303",
 211        "CH7301",
 212        "INTERNAL_DVO1",
 213        "EXTERNAL_SDVOA",
 214        "EXTERNAL_SDVOB",
 215        "TITFP513",
 216        "INTERNAL_LVTM1",
 217        "VT1623",
 218        "HDMI_SI1930",
 219        "HDMI_INTERNAL",
 220        "INTERNAL_KLDSCP_TMDS1",
 221        "INTERNAL_KLDSCP_DVO1",
 222        "INTERNAL_KLDSCP_DAC1",
 223        "INTERNAL_KLDSCP_DAC2",
 224        "SI178",
 225        "MVPU_FPGA",
 226        "INTERNAL_DDI",
 227        "VT1625",
 228        "HDMI_SI1932",
 229        "DP_AN9801",
 230        "DP_DP501",
 231        "INTERNAL_UNIPHY",
 232        "INTERNAL_KLDSCP_LVTMA",
 233        "INTERNAL_UNIPHY1",
 234        "INTERNAL_UNIPHY2",
 235};
 236
 237static const char *connector_names[13] = {
 238        "Unknown",
 239        "VGA",
 240        "DVI-I",
 241        "DVI-D",
 242        "DVI-A",
 243        "Composite",
 244        "S-video",
 245        "LVDS",
 246        "Component",
 247        "DIN",
 248        "DisplayPort",
 249        "HDMI-A",
 250        "HDMI-B",
 251};
 252
 253static void radeon_print_display_setup(struct drm_device *dev)
 254{
 255        struct drm_connector *connector;
 256        struct radeon_connector *radeon_connector;
 257        struct drm_encoder *encoder;
 258        struct radeon_encoder *radeon_encoder;
 259        uint32_t devices;
 260        int i = 0;
 261
 262        DRM_INFO("Radeon Display Connectors\n");
 263        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 264                radeon_connector = to_radeon_connector(connector);
 265                DRM_INFO("Connector %d:\n", i);
 266                DRM_INFO("  %s\n", connector_names[connector->connector_type]);
 267                if (radeon_connector->ddc_bus)
 268                        DRM_INFO("  DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
 269                                 radeon_connector->ddc_bus->rec.mask_clk_reg,
 270                                 radeon_connector->ddc_bus->rec.mask_data_reg,
 271                                 radeon_connector->ddc_bus->rec.a_clk_reg,
 272                                 radeon_connector->ddc_bus->rec.a_data_reg,
 273                                 radeon_connector->ddc_bus->rec.put_clk_reg,
 274                                 radeon_connector->ddc_bus->rec.put_data_reg,
 275                                 radeon_connector->ddc_bus->rec.get_clk_reg,
 276                                 radeon_connector->ddc_bus->rec.get_data_reg);
 277                DRM_INFO("  Encoders:\n");
 278                list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 279                        radeon_encoder = to_radeon_encoder(encoder);
 280                        devices = radeon_encoder->devices & radeon_connector->devices;
 281                        if (devices) {
 282                                if (devices & ATOM_DEVICE_CRT1_SUPPORT)
 283                                        DRM_INFO("    CRT1: %s\n", encoder_names[radeon_encoder->encoder_id]);
 284                                if (devices & ATOM_DEVICE_CRT2_SUPPORT)
 285                                        DRM_INFO("    CRT2: %s\n", encoder_names[radeon_encoder->encoder_id]);
 286                                if (devices & ATOM_DEVICE_LCD1_SUPPORT)
 287                                        DRM_INFO("    LCD1: %s\n", encoder_names[radeon_encoder->encoder_id]);
 288                                if (devices & ATOM_DEVICE_DFP1_SUPPORT)
 289                                        DRM_INFO("    DFP1: %s\n", encoder_names[radeon_encoder->encoder_id]);
 290                                if (devices & ATOM_DEVICE_DFP2_SUPPORT)
 291                                        DRM_INFO("    DFP2: %s\n", encoder_names[radeon_encoder->encoder_id]);
 292                                if (devices & ATOM_DEVICE_DFP3_SUPPORT)
 293                                        DRM_INFO("    DFP3: %s\n", encoder_names[radeon_encoder->encoder_id]);
 294                                if (devices & ATOM_DEVICE_DFP4_SUPPORT)
 295                                        DRM_INFO("    DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]);
 296                                if (devices & ATOM_DEVICE_DFP5_SUPPORT)
 297                                        DRM_INFO("    DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]);
 298                                if (devices & ATOM_DEVICE_TV1_SUPPORT)
 299                                        DRM_INFO("    TV1: %s\n", encoder_names[radeon_encoder->encoder_id]);
 300                                if (devices & ATOM_DEVICE_CV_SUPPORT)
 301                                        DRM_INFO("    CV: %s\n", encoder_names[radeon_encoder->encoder_id]);
 302                        }
 303                }
 304                i++;
 305        }
 306}
 307
 308static bool radeon_setup_enc_conn(struct drm_device *dev)
 309{
 310        struct radeon_device *rdev = dev->dev_private;
 311        struct drm_connector *drm_connector;
 312        bool ret = false;
 313
 314        if (rdev->bios) {
 315                if (rdev->is_atom_bios) {
 316                        if (rdev->family >= CHIP_R600)
 317                                ret = radeon_get_atom_connector_info_from_object_table(dev);
 318                        else
 319                                ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
 320                } else
 321                        ret = radeon_get_legacy_connector_info_from_bios(dev);
 322        } else {
 323                if (!ASIC_IS_AVIVO(rdev))
 324                        ret = radeon_get_legacy_connector_info_from_table(dev);
 325        }
 326        if (ret) {
 327                radeon_print_display_setup(dev);
 328                list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
 329                        radeon_ddc_dump(drm_connector);
 330        }
 331
 332        return ret;
 333}
 334
 335int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
 336{
 337        int ret = 0;
 338
 339        if (!radeon_connector->ddc_bus)
 340                return -1;
 341        if (!radeon_connector->edid) {
 342                radeon_i2c_do_lock(radeon_connector, 1);
 343                radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
 344                radeon_i2c_do_lock(radeon_connector, 0);
 345        }
 346
 347        if (radeon_connector->edid) {
 348                drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
 349                ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
 350                return ret;
 351        }
 352        drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
 353        return 0;
 354}
 355
 356static int radeon_ddc_dump(struct drm_connector *connector)
 357{
 358        struct edid *edid;
 359        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 360        int ret = 0;
 361
 362        if (!radeon_connector->ddc_bus)
 363                return -1;
 364        radeon_i2c_do_lock(radeon_connector, 1);
 365        edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
 366        radeon_i2c_do_lock(radeon_connector, 0);
 367        if (edid) {
 368                kfree(edid);
 369        }
 370        return ret;
 371}
 372
 373static inline uint32_t radeon_div(uint64_t n, uint32_t d)
 374{
 375        uint64_t mod;
 376
 377        n += d / 2;
 378
 379        mod = do_div(n, d);
 380        return n;
 381}
 382
 383void radeon_compute_pll(struct radeon_pll *pll,
 384                        uint64_t freq,
 385                        uint32_t *dot_clock_p,
 386                        uint32_t *fb_div_p,
 387                        uint32_t *frac_fb_div_p,
 388                        uint32_t *ref_div_p,
 389                        uint32_t *post_div_p,
 390                        int flags)
 391{
 392        uint32_t min_ref_div = pll->min_ref_div;
 393        uint32_t max_ref_div = pll->max_ref_div;
 394        uint32_t min_fractional_feed_div = 0;
 395        uint32_t max_fractional_feed_div = 0;
 396        uint32_t best_vco = pll->best_vco;
 397        uint32_t best_post_div = 1;
 398        uint32_t best_ref_div = 1;
 399        uint32_t best_feedback_div = 1;
 400        uint32_t best_frac_feedback_div = 0;
 401        uint32_t best_freq = -1;
 402        uint32_t best_error = 0xffffffff;
 403        uint32_t best_vco_diff = 1;
 404        uint32_t post_div;
 405
 406        DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div);
 407        freq = freq * 1000;
 408
 409        if (flags & RADEON_PLL_USE_REF_DIV)
 410                min_ref_div = max_ref_div = pll->reference_div;
 411        else {
 412                while (min_ref_div < max_ref_div-1) {
 413                        uint32_t mid = (min_ref_div + max_ref_div) / 2;
 414                        uint32_t pll_in = pll->reference_freq / mid;
 415                        if (pll_in < pll->pll_in_min)
 416                                max_ref_div = mid;
 417                        else if (pll_in > pll->pll_in_max)
 418                                min_ref_div = mid;
 419                        else
 420                                break;
 421                }
 422        }
 423
 424        if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
 425                min_fractional_feed_div = pll->min_frac_feedback_div;
 426                max_fractional_feed_div = pll->max_frac_feedback_div;
 427        }
 428
 429        for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
 430                uint32_t ref_div;
 431
 432                if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
 433                        continue;
 434
 435                /* legacy radeons only have a few post_divs */
 436                if (flags & RADEON_PLL_LEGACY) {
 437                        if ((post_div == 5) ||
 438                            (post_div == 7) ||
 439                            (post_div == 9) ||
 440                            (post_div == 10) ||
 441                            (post_div == 11) ||
 442                            (post_div == 13) ||
 443                            (post_div == 14) ||
 444                            (post_div == 15))
 445                                continue;
 446                }
 447
 448                for (ref_div = min_ref_div; ref_div <= max_ref_div; ++ref_div) {
 449                        uint32_t feedback_div, current_freq = 0, error, vco_diff;
 450                        uint32_t pll_in = pll->reference_freq / ref_div;
 451                        uint32_t min_feed_div = pll->min_feedback_div;
 452                        uint32_t max_feed_div = pll->max_feedback_div + 1;
 453
 454                        if (pll_in < pll->pll_in_min || pll_in > pll->pll_in_max)
 455                                continue;
 456
 457                        while (min_feed_div < max_feed_div) {
 458                                uint32_t vco;
 459                                uint32_t min_frac_feed_div = min_fractional_feed_div;
 460                                uint32_t max_frac_feed_div = max_fractional_feed_div + 1;
 461                                uint32_t frac_feedback_div;
 462                                uint64_t tmp;
 463
 464                                feedback_div = (min_feed_div + max_feed_div) / 2;
 465
 466                                tmp = (uint64_t)pll->reference_freq * feedback_div;
 467                                vco = radeon_div(tmp, ref_div);
 468
 469                                if (vco < pll->pll_out_min) {
 470                                        min_feed_div = feedback_div + 1;
 471                                        continue;
 472                                } else if (vco > pll->pll_out_max) {
 473                                        max_feed_div = feedback_div;
 474                                        continue;
 475                                }
 476
 477                                while (min_frac_feed_div < max_frac_feed_div) {
 478                                        frac_feedback_div = (min_frac_feed_div + max_frac_feed_div) / 2;
 479                                        tmp = (uint64_t)pll->reference_freq * 10000 * feedback_div;
 480                                        tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div;
 481                                        current_freq = radeon_div(tmp, ref_div * post_div);
 482
 483                                        if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
 484                                                error = freq - current_freq;
 485                                                error = error < 0 ? 0xffffffff : error;
 486                                        } else
 487                                                error = abs(current_freq - freq);
 488                                        vco_diff = abs(vco - best_vco);
 489
 490                                        if ((best_vco == 0 && error < best_error) ||
 491                                            (best_vco != 0 &&
 492                                             (error < best_error - 100 ||
 493                                              (abs(error - best_error) < 100 && vco_diff < best_vco_diff)))) {
 494                                                best_post_div = post_div;
 495                                                best_ref_div = ref_div;
 496                                                best_feedback_div = feedback_div;
 497                                                best_frac_feedback_div = frac_feedback_div;
 498                                                best_freq = current_freq;
 499                                                best_error = error;
 500                                                best_vco_diff = vco_diff;
 501                                        } else if (current_freq == freq) {
 502                                                if (best_freq == -1) {
 503                                                        best_post_div = post_div;
 504                                                        best_ref_div = ref_div;
 505                                                        best_feedback_div = feedback_div;
 506                                                        best_frac_feedback_div = frac_feedback_div;
 507                                                        best_freq = current_freq;
 508                                                        best_error = error;
 509                                                        best_vco_diff = vco_diff;
 510                                                } else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
 511                                                           ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
 512                                                           ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
 513                                                           ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
 514                                                           ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
 515                                                           ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
 516                                                        best_post_div = post_div;
 517                                                        best_ref_div = ref_div;
 518                                                        best_feedback_div = feedback_div;
 519                                                        best_frac_feedback_div = frac_feedback_div;
 520                                                        best_freq = current_freq;
 521                                                        best_error = error;
 522                                                        best_vco_diff = vco_diff;
 523                                                }
 524                                        }
 525                                        if (current_freq < freq)
 526                                                min_frac_feed_div = frac_feedback_div + 1;
 527                                        else
 528                                                max_frac_feed_div = frac_feedback_div;
 529                                }
 530                                if (current_freq < freq)
 531                                        min_feed_div = feedback_div + 1;
 532                                else
 533                                        max_feed_div = feedback_div;
 534                        }
 535                }
 536        }
 537
 538        *dot_clock_p = best_freq / 10000;
 539        *fb_div_p = best_feedback_div;
 540        *frac_fb_div_p = best_frac_feedback_div;
 541        *ref_div_p = best_ref_div;
 542        *post_div_p = best_post_div;
 543}
 544
 545static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
 546{
 547        struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
 548        struct drm_device *dev = fb->dev;
 549
 550        if (fb->fbdev)
 551                radeonfb_remove(dev, fb);
 552
 553        if (radeon_fb->obj) {
 554                radeon_gem_object_unpin(radeon_fb->obj);
 555                mutex_lock(&dev->struct_mutex);
 556                drm_gem_object_unreference(radeon_fb->obj);
 557                mutex_unlock(&dev->struct_mutex);
 558        }
 559        drm_framebuffer_cleanup(fb);
 560        kfree(radeon_fb);
 561}
 562
 563static int radeon_user_framebuffer_create_handle(struct drm_framebuffer *fb,
 564                                                  struct drm_file *file_priv,
 565                                                  unsigned int *handle)
 566{
 567        struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
 568
 569        return drm_gem_handle_create(file_priv, radeon_fb->obj, handle);
 570}
 571
 572static const struct drm_framebuffer_funcs radeon_fb_funcs = {
 573        .destroy = radeon_user_framebuffer_destroy,
 574        .create_handle = radeon_user_framebuffer_create_handle,
 575};
 576
 577struct drm_framebuffer *
 578radeon_framebuffer_create(struct drm_device *dev,
 579                          struct drm_mode_fb_cmd *mode_cmd,
 580                          struct drm_gem_object *obj)
 581{
 582        struct radeon_framebuffer *radeon_fb;
 583
 584        radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL);
 585        if (radeon_fb == NULL) {
 586                return NULL;
 587        }
 588        drm_framebuffer_init(dev, &radeon_fb->base, &radeon_fb_funcs);
 589        drm_helper_mode_fill_fb_struct(&radeon_fb->base, mode_cmd);
 590        radeon_fb->obj = obj;
 591        return &radeon_fb->base;
 592}
 593
 594static struct drm_framebuffer *
 595radeon_user_framebuffer_create(struct drm_device *dev,
 596                               struct drm_file *file_priv,
 597                               struct drm_mode_fb_cmd *mode_cmd)
 598{
 599        struct drm_gem_object *obj;
 600
 601        obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
 602
 603        return radeon_framebuffer_create(dev, mode_cmd, obj);
 604}
 605
 606static const struct drm_mode_config_funcs radeon_mode_funcs = {
 607        .fb_create = radeon_user_framebuffer_create,
 608        .fb_changed = radeonfb_probe,
 609};
 610
 611struct drm_prop_enum_list {
 612        int type;
 613        char *name;
 614};
 615
 616static struct drm_prop_enum_list radeon_tmds_pll_enum_list[] =
 617{       { 0, "driver" },
 618        { 1, "bios" },
 619};
 620
 621static struct drm_prop_enum_list radeon_tv_std_enum_list[] =
 622{       { TV_STD_NTSC, "ntsc" },
 623        { TV_STD_PAL, "pal" },
 624        { TV_STD_PAL_M, "pal-m" },
 625        { TV_STD_PAL_60, "pal-60" },
 626        { TV_STD_NTSC_J, "ntsc-j" },
 627        { TV_STD_SCART_PAL, "scart-pal" },
 628        { TV_STD_PAL_CN, "pal-cn" },
 629        { TV_STD_SECAM, "secam" },
 630};
 631
 632int radeon_modeset_create_props(struct radeon_device *rdev)
 633{
 634        int i, sz;
 635
 636        if (rdev->is_atom_bios) {
 637                rdev->mode_info.coherent_mode_property =
 638                        drm_property_create(rdev->ddev,
 639                                            DRM_MODE_PROP_RANGE,
 640                                            "coherent", 2);
 641                if (!rdev->mode_info.coherent_mode_property)
 642                        return -ENOMEM;
 643
 644                rdev->mode_info.coherent_mode_property->values[0] = 0;
 645                rdev->mode_info.coherent_mode_property->values[0] = 1;
 646        }
 647
 648        if (!ASIC_IS_AVIVO(rdev)) {
 649                sz = ARRAY_SIZE(radeon_tmds_pll_enum_list);
 650                rdev->mode_info.tmds_pll_property =
 651                        drm_property_create(rdev->ddev,
 652                                            DRM_MODE_PROP_ENUM,
 653                                            "tmds_pll", sz);
 654                for (i = 0; i < sz; i++) {
 655                        drm_property_add_enum(rdev->mode_info.tmds_pll_property,
 656                                              i,
 657                                              radeon_tmds_pll_enum_list[i].type,
 658                                              radeon_tmds_pll_enum_list[i].name);
 659                }
 660        }
 661
 662        rdev->mode_info.load_detect_property =
 663                drm_property_create(rdev->ddev,
 664                                    DRM_MODE_PROP_RANGE,
 665                                    "load detection", 2);
 666        if (!rdev->mode_info.load_detect_property)
 667                return -ENOMEM;
 668        rdev->mode_info.load_detect_property->values[0] = 0;
 669        rdev->mode_info.load_detect_property->values[0] = 1;
 670
 671        drm_mode_create_scaling_mode_property(rdev->ddev);
 672
 673        sz = ARRAY_SIZE(radeon_tv_std_enum_list);
 674        rdev->mode_info.tv_std_property =
 675                drm_property_create(rdev->ddev,
 676                                    DRM_MODE_PROP_ENUM,
 677                                    "tv standard", sz);
 678        for (i = 0; i < sz; i++) {
 679                drm_property_add_enum(rdev->mode_info.tv_std_property,
 680                                      i,
 681                                      radeon_tv_std_enum_list[i].type,
 682                                      radeon_tv_std_enum_list[i].name);
 683        }
 684
 685        return 0;
 686}
 687
 688int radeon_modeset_init(struct radeon_device *rdev)
 689{
 690        int num_crtc = 2, i;
 691        int ret;
 692
 693        drm_mode_config_init(rdev->ddev);
 694        rdev->mode_info.mode_config_initialized = true;
 695
 696        rdev->ddev->mode_config.funcs = (void *)&radeon_mode_funcs;
 697
 698        if (ASIC_IS_AVIVO(rdev)) {
 699                rdev->ddev->mode_config.max_width = 8192;
 700                rdev->ddev->mode_config.max_height = 8192;
 701        } else {
 702                rdev->ddev->mode_config.max_width = 4096;
 703                rdev->ddev->mode_config.max_height = 4096;
 704        }
 705
 706        rdev->ddev->mode_config.fb_base = rdev->mc.aper_base;
 707
 708        ret = radeon_modeset_create_props(rdev);
 709        if (ret) {
 710                return ret;
 711        }
 712
 713        if (rdev->flags & RADEON_SINGLE_CRTC)
 714                num_crtc = 1;
 715
 716        /* allocate crtcs */
 717        for (i = 0; i < num_crtc; i++) {
 718                radeon_crtc_init(rdev->ddev, i);
 719        }
 720
 721        /* okay we should have all the bios connectors */
 722        ret = radeon_setup_enc_conn(rdev->ddev);
 723        if (!ret) {
 724                return ret;
 725        }
 726        drm_helper_initial_config(rdev->ddev);
 727        return 0;
 728}
 729
 730void radeon_modeset_fini(struct radeon_device *rdev)
 731{
 732        if (rdev->mode_info.mode_config_initialized) {
 733                drm_mode_config_cleanup(rdev->ddev);
 734                rdev->mode_info.mode_config_initialized = false;
 735        }
 736}
 737
 738bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
 739                                struct drm_display_mode *mode,
 740                                struct drm_display_mode *adjusted_mode)
 741{
 742        struct drm_device *dev = crtc->dev;
 743        struct drm_encoder *encoder;
 744        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 745        struct radeon_encoder *radeon_encoder;
 746        bool first = true;
 747
 748        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 749                radeon_encoder = to_radeon_encoder(encoder);
 750                if (encoder->crtc != crtc)
 751                        continue;
 752                if (first) {
 753                        radeon_crtc->rmx_type = radeon_encoder->rmx_type;
 754                        memcpy(&radeon_crtc->native_mode,
 755                                &radeon_encoder->native_mode,
 756                                sizeof(struct drm_display_mode));
 757                        first = false;
 758                } else {
 759                        if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) {
 760                                /* WARNING: Right now this can't happen but
 761                                 * in the future we need to check that scaling
 762                                 * are consistent accross different encoder
 763                                 * (ie all encoder can work with the same
 764                                 *  scaling).
 765                                 */
 766                                DRM_ERROR("Scaling not consistent accross encoder.\n");
 767                                return false;
 768                        }
 769                }
 770        }
 771        if (radeon_crtc->rmx_type != RMX_OFF) {
 772                fixed20_12 a, b;
 773                a.full = rfixed_const(crtc->mode.vdisplay);
 774                b.full = rfixed_const(radeon_crtc->native_mode.hdisplay);
 775                radeon_crtc->vsc.full = rfixed_div(a, b);
 776                a.full = rfixed_const(crtc->mode.hdisplay);
 777                b.full = rfixed_const(radeon_crtc->native_mode.vdisplay);
 778                radeon_crtc->hsc.full = rfixed_div(a, b);
 779        } else {
 780                radeon_crtc->vsc.full = rfixed_const(1);
 781                radeon_crtc->hsc.full = rfixed_const(1);
 782        }
 783        return true;
 784}
 785