linux/drivers/video/fbdev/via/dvi.c
<<
>>
Prefs
   1/*
   2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
   3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
   4
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public
   7 * License as published by the Free Software Foundation;
   8 * either version 2, or (at your option) any later version.
   9
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
  12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
  13 * A PARTICULAR PURPOSE.See the GNU General Public License
  14 * for more details.
  15
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc.,
  19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20 */
  21#include <linux/via-core.h>
  22#include <linux/via_i2c.h>
  23#include "global.h"
  24
  25static void tmds_register_write(int index, u8 data);
  26static int tmds_register_read(int index);
  27static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
  28static void dvi_get_panel_size_from_DDCv1(
  29        struct tmds_chip_information *tmds_chip,
  30        struct tmds_setting_information *tmds_setting);
  31static int viafb_dvi_query_EDID(void);
  32
  33static inline bool check_tmds_chip(int device_id_subaddr, int device_id)
  34{
  35        return tmds_register_read(device_id_subaddr) == device_id;
  36}
  37
  38void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
  39                         struct tmds_setting_information *tmds_setting)
  40{
  41        DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
  42
  43        viafb_dvi_sense();
  44        if (viafb_dvi_query_EDID() == 1)
  45                dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting);
  46
  47        return;
  48}
  49
  50bool viafb_tmds_trasmitter_identify(void)
  51{
  52        unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
  53
  54        /* Turn on ouputting pad */
  55        switch (viaparinfo->chip_info->gfx_chip_name) {
  56        case UNICHROME_K8M890:
  57            /*=* DFP Low Pad on *=*/
  58                sr2a = viafb_read_reg(VIASR, SR2A);
  59                viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
  60                break;
  61
  62        case UNICHROME_P4M900:
  63        case UNICHROME_P4M890:
  64                /* DFP Low Pad on */
  65                sr2a = viafb_read_reg(VIASR, SR2A);
  66                viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
  67                /* DVP0 Pad on */
  68                sr1e = viafb_read_reg(VIASR, SR1E);
  69                viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7);
  70                break;
  71
  72        default:
  73            /* DVP0/DVP1 Pad on */
  74                sr1e = viafb_read_reg(VIASR, SR1E);
  75                viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 +
  76                        BIT5 + BIT6 + BIT7);
  77            /* SR3E[1]Multi-function selection:
  78            0 = Emulate I2C and DDC bus by GPIO2/3/4. */
  79                sr3e = viafb_read_reg(VIASR, SR3E);
  80                viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5);
  81                break;
  82        }
  83
  84        /* Check for VT1632: */
  85        viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;
  86        viaparinfo->chip_info->
  87                tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
  88        viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31;
  89        if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {
  90                /*
  91                 * Currently only support 12bits,dual edge,add 24bits mode later
  92                 */
  93                tmds_register_write(0x08, 0x3b);
  94
  95                DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
  96                DEBUG_MSG(KERN_INFO "\n %2d",
  97                          viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
  98                DEBUG_MSG(KERN_INFO "\n %2d",
  99                          viaparinfo->chip_info->tmds_chip_info.i2c_port);
 100                return true;
 101        } else {
 102                viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C;
 103                if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {
 104                        tmds_register_write(0x08, 0x3b);
 105                        DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
 106                        DEBUG_MSG(KERN_INFO "\n %2d",
 107                                  viaparinfo->chip_info->
 108                                  tmds_chip_info.tmds_chip_name);
 109                        DEBUG_MSG(KERN_INFO "\n %2d",
 110                                  viaparinfo->chip_info->
 111                                  tmds_chip_info.i2c_port);
 112                        return true;
 113                }
 114        }
 115
 116        viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS;
 117
 118        if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) &&
 119            ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
 120             (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {
 121                DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");
 122                return true;
 123        }
 124
 125        switch (viaparinfo->chip_info->gfx_chip_name) {
 126        case UNICHROME_K8M890:
 127                viafb_write_reg(SR2A, VIASR, sr2a);
 128                break;
 129
 130        case UNICHROME_P4M900:
 131        case UNICHROME_P4M890:
 132                viafb_write_reg(SR2A, VIASR, sr2a);
 133                viafb_write_reg(SR1E, VIASR, sr1e);
 134                break;
 135
 136        default:
 137                viafb_write_reg(SR1E, VIASR, sr1e);
 138                viafb_write_reg(SR3E, VIASR, sr3e);
 139                break;
 140        }
 141
 142        viaparinfo->chip_info->
 143                tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;
 144        viaparinfo->chip_info->tmds_chip_info.
 145                tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
 146        return false;
 147}
 148
 149static void tmds_register_write(int index, u8 data)
 150{
 151        viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
 152                            viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
 153                            index, data);
 154}
 155
 156static int tmds_register_read(int index)
 157{
 158        u8 data;
 159
 160        viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
 161                           (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
 162                           (u8) index, &data);
 163        return data;
 164}
 165
 166static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
 167{
 168        viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port,
 169                            (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
 170                            (u8) index, buff, buff_len);
 171        return 0;
 172}
 173
 174/* DVI Set Mode */
 175void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
 176        u16 cxres, u16 cyres, int iga)
 177{
 178        struct fb_var_screeninfo dvi_var = *var;
 179        const struct fb_videomode *rb_mode;
 180        int maxPixelClock;
 181
 182        maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;
 183        if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) {
 184                rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60);
 185                if (rb_mode)
 186                        viafb_fill_var_timing_info(&dvi_var, rb_mode);
 187        }
 188
 189        viafb_fill_crtc_timing(&dvi_var, cxres, cyres, iga);
 190}
 191
 192/* Sense DVI Connector */
 193int viafb_dvi_sense(void)
 194{
 195        u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0,
 196                RegCR93 = 0, RegCR9B = 0, data;
 197        int ret = false;
 198
 199        DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n");
 200
 201        if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
 202                /* DI1 Pad on */
 203                RegSR1E = viafb_read_reg(VIASR, SR1E);
 204                viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30);
 205
 206                /* CR6B[0]VCK Input Selection: 1 = External clock. */
 207                RegCR6B = viafb_read_reg(VIACR, CR6B);
 208                viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08);
 209
 210                /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
 211                   [0] Software Control Power Sequence */
 212                RegCR91 = viafb_read_reg(VIACR, CR91);
 213                viafb_write_reg(CR91, VIACR, 0x1D);
 214
 215                /* CR93[7] DI1 Data Source Selection: 1 = DSP2.
 216                   CR93[5] DI1 Clock Source: 1 = internal.
 217                   CR93[4] DI1 Clock Polarity.
 218                   CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */
 219                RegCR93 = viafb_read_reg(VIACR, CR93);
 220                viafb_write_reg(CR93, VIACR, 0x01);
 221        } else {
 222                /* DVP0/DVP1 Pad on */
 223                RegSR1E = viafb_read_reg(VIASR, SR1E);
 224                viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0);
 225
 226                /* SR3E[1]Multi-function selection:
 227                   0 = Emulate I2C and DDC bus by GPIO2/3/4. */
 228                RegSR3E = viafb_read_reg(VIASR, SR3E);
 229                viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20));
 230
 231                /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
 232                   [0] Software Control Power Sequence */
 233                RegCR91 = viafb_read_reg(VIACR, CR91);
 234                viafb_write_reg(CR91, VIACR, 0x1D);
 235
 236                /*CR9B[4] DVP1 Data Source Selection: 1 = From secondary
 237                display.CR9B[2:0] DVP1 Clock Adjust */
 238                RegCR9B = viafb_read_reg(VIACR, CR9B);
 239                viafb_write_reg(CR9B, VIACR, 0x01);
 240        }
 241
 242        data = (u8) tmds_register_read(0x09);
 243        if (data & 0x04)
 244                ret = true;
 245
 246        if (ret == false) {
 247                if (viafb_dvi_query_EDID())
 248                        ret = true;
 249        }
 250
 251        /* Restore status */
 252        viafb_write_reg(SR1E, VIASR, RegSR1E);
 253        viafb_write_reg(CR91, VIACR, RegCR91);
 254        if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
 255                viafb_write_reg(CR6B, VIACR, RegCR6B);
 256                viafb_write_reg(CR93, VIACR, RegCR93);
 257        } else {
 258                viafb_write_reg(SR3E, VIASR, RegSR3E);
 259                viafb_write_reg(CR9B, VIACR, RegCR9B);
 260        }
 261
 262        return ret;
 263}
 264
 265/* Query Flat Panel's EDID Table Version Through DVI Connector */
 266static int viafb_dvi_query_EDID(void)
 267{
 268        u8 data0, data1;
 269        int restore;
 270
 271        DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n");
 272
 273        restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
 274        viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
 275
 276        data0 = (u8) tmds_register_read(0x00);
 277        data1 = (u8) tmds_register_read(0x01);
 278        if ((data0 == 0) && (data1 == 0xFF)) {
 279                viaparinfo->chip_info->
 280                        tmds_chip_info.tmds_chip_slave_addr = restore;
 281                return EDID_VERSION_1;  /* Found EDID1 Table */
 282        }
 283
 284        return false;
 285}
 286
 287/* Get Panel Size Using EDID1 Table */
 288static void dvi_get_panel_size_from_DDCv1(
 289        struct tmds_chip_information *tmds_chip,
 290        struct tmds_setting_information *tmds_setting)
 291{
 292        int i, restore;
 293        unsigned char EDID_DATA[18];
 294
 295        DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
 296
 297        restore = tmds_chip->tmds_chip_slave_addr;
 298        tmds_chip->tmds_chip_slave_addr = 0xA0;
 299        for (i = 0x25; i < 0x6D; i++) {
 300                switch (i) {
 301                case 0x36:
 302                case 0x48:
 303                case 0x5A:
 304                case 0x6C:
 305                        tmds_register_read_bytes(i, EDID_DATA, 10);
 306                        if (!(EDID_DATA[0] || EDID_DATA[1])) {
 307                                /* The first two byte must be zero. */
 308                                if (EDID_DATA[3] == 0xFD) {
 309                                        /* To get max pixel clock. */
 310                                        tmds_setting->max_pixel_clock =
 311                                                EDID_DATA[9] * 10;
 312                                }
 313                        }
 314                        break;
 315
 316                default:
 317                        break;
 318                }
 319        }
 320
 321        DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
 322                tmds_setting->max_pixel_clock);
 323        tmds_chip->tmds_chip_slave_addr = restore;
 324}
 325
 326/* If Disable DVI, turn off pad */
 327void viafb_dvi_disable(void)
 328{
 329        if (viaparinfo->chip_info->
 330                tmds_chip_info.output_interface == INTERFACE_TMDS)
 331                /* Turn off TMDS power. */
 332                viafb_write_reg(CRD2, VIACR,
 333                viafb_read_reg(VIACR, CRD2) | 0x08);
 334}
 335
 336static void dvi_patch_skew_dvp0(void)
 337{
 338        /* Reset data driving first: */
 339        viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);
 340        viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
 341
 342        switch (viaparinfo->chip_info->gfx_chip_name) {
 343        case UNICHROME_P4M890:
 344                {
 345                        if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
 346                                (viaparinfo->tmds_setting_info->v_active ==
 347                                1200))
 348                                viafb_write_reg_mask(CR96, VIACR, 0x03,
 349                                               BIT0 + BIT1 + BIT2);
 350                        else
 351                                viafb_write_reg_mask(CR96, VIACR, 0x07,
 352                                               BIT0 + BIT1 + BIT2);
 353                        break;
 354                }
 355
 356        case UNICHROME_P4M900:
 357                {
 358                        viafb_write_reg_mask(CR96, VIACR, 0x07,
 359                                       BIT0 + BIT1 + BIT2 + BIT3);
 360                        viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
 361                        viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
 362                        break;
 363                }
 364
 365        default:
 366                {
 367                        break;
 368                }
 369        }
 370}
 371
 372static void dvi_patch_skew_dvp_low(void)
 373{
 374        switch (viaparinfo->chip_info->gfx_chip_name) {
 375        case UNICHROME_K8M890:
 376                {
 377                        viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
 378                        break;
 379                }
 380
 381        case UNICHROME_P4M900:
 382                {
 383                        viafb_write_reg_mask(CR99, VIACR, 0x08,
 384                                       BIT0 + BIT1 + BIT2 + BIT3);
 385                        break;
 386                }
 387
 388        case UNICHROME_P4M890:
 389                {
 390                        viafb_write_reg_mask(CR99, VIACR, 0x0F,
 391                                       BIT0 + BIT1 + BIT2 + BIT3);
 392                        break;
 393                }
 394
 395        default:
 396                {
 397                        break;
 398                }
 399        }
 400}
 401
 402/* If Enable DVI, turn off pad */
 403void viafb_dvi_enable(void)
 404{
 405        u8 data;
 406
 407        switch (viaparinfo->chip_info->tmds_chip_info.output_interface) {
 408        case INTERFACE_DVP0:
 409                viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
 410                viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5);
 411                dvi_patch_skew_dvp0();
 412                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 413                        tmds_register_write(0x88, 0x3b);
 414                else
 415                        /*clear CR91[5] to direct on display period
 416                           in the secondary diplay path */
 417                        via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
 418                break;
 419
 420        case INTERFACE_DVP1:
 421                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 422                        viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5);
 423
 424                /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
 425                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 426                        tmds_register_write(0x88, 0x3b);
 427                else
 428                        /*clear CR91[5] to direct on display period
 429                          in the secondary diplay path */
 430                        via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
 431
 432                /*fix DVI cannot enable on EPIA-M board */
 433                if (viafb_platform_epia_dvi == 1) {
 434                        viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f);
 435                        viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0);
 436                        if (viafb_bus_width == 24) {
 437                                if (viafb_device_lcd_dualedge == 1)
 438                                        data = 0x3F;
 439                                else
 440                                        data = 0x37;
 441                                viafb_i2c_writebyte(viaparinfo->chip_info->
 442                                        tmds_chip_info.i2c_port,
 443                                        viaparinfo->chip_info->
 444                                        tmds_chip_info.tmds_chip_slave_addr,
 445                                        0x08, data);
 446                        }
 447                }
 448                break;
 449
 450        case INTERFACE_DFP_HIGH:
 451                if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
 452                        via_write_reg_mask(VIACR, CR97, 0x03, 0x03);
 453
 454                via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
 455                break;
 456
 457        case INTERFACE_DFP_LOW:
 458                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 459                        break;
 460
 461                dvi_patch_skew_dvp_low();
 462                via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
 463                break;
 464
 465        case INTERFACE_TMDS:
 466                /* Turn on Display period in the panel path. */
 467                viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
 468
 469                /* Turn on TMDS power. */
 470                viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
 471                break;
 472        }
 473
 474        if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
 475                /* Disable LCD Scaling */
 476                viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
 477        }
 478}
 479