linux/drivers/video/fbdev/via/vt1636.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
  22#include <linux/via-core.h>
  23#include <linux/via_i2c.h>
  24#include "global.h"
  25
  26static const struct IODATA common_init_data[] = {
  27/*  Index, Mask, Value */
  28        /* Set panel power sequence timing */
  29        {0x10, 0xC0, 0x00},
  30        /* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
  31        {0x0B, 0xFF, 0x40},
  32        /* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
  33        {0x0C, 0xFF, 0x31},
  34        /* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
  35        {0x0D, 0xFF, 0x31},
  36        /* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
  37        {0x0E, 0xFF, 0x68},
  38        /* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
  39        {0x0F, 0xFF, 0x68},
  40        /* LVDS output power up */
  41        {0x09, 0xA0, 0xA0},
  42        /* turn on back light */
  43        {0x10, 0x33, 0x13}
  44};
  45
  46/* Index, Mask, Value */
  47static const struct IODATA dual_channel_enable_data = {0x08, 0xF0, 0xE0};
  48static const struct IODATA single_channel_enable_data = {0x08, 0xF0, 0x00};
  49static const struct IODATA dithering_enable_data = {0x0A, 0x70, 0x50};
  50static const struct IODATA dithering_disable_data = {0x0A, 0x70, 0x00};
  51static const struct IODATA vdd_on_data = {0x10, 0x20, 0x20};
  52static const struct IODATA vdd_off_data = {0x10, 0x20, 0x00};
  53
  54u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
  55        *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
  56        u8 index)
  57{
  58        u8 data;
  59
  60        viafb_i2c_readbyte(plvds_chip_info->i2c_port,
  61                           plvds_chip_info->lvds_chip_slave_addr, index, &data);
  62        return data;
  63}
  64
  65void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
  66                              *plvds_setting_info, struct lvds_chip_information
  67                              *plvds_chip_info, struct IODATA io_data)
  68{
  69        int index, data;
  70
  71        index = io_data.Index;
  72        data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
  73                index);
  74        data = (data & (~io_data.Mask)) | io_data.Data;
  75
  76        viafb_i2c_writebyte(plvds_chip_info->i2c_port,
  77                            plvds_chip_info->lvds_chip_slave_addr, index, data);
  78}
  79
  80void viafb_init_lvds_vt1636(struct lvds_setting_information
  81        *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
  82{
  83        int reg_num, i;
  84
  85        /* Common settings: */
  86        reg_num = ARRAY_SIZE(common_init_data);
  87        for (i = 0; i < reg_num; i++)
  88                viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
  89                        plvds_chip_info, common_init_data[i]);
  90
  91        /* Input Data Mode Select */
  92        if (plvds_setting_info->device_lcd_dualedge)
  93                viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
  94                        plvds_chip_info, dual_channel_enable_data);
  95        else
  96                viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
  97                        plvds_chip_info, single_channel_enable_data);
  98
  99        if (plvds_setting_info->LCDDithering)
 100                viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
 101                        plvds_chip_info, dithering_enable_data);
 102        else
 103                viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
 104                        plvds_chip_info, dithering_disable_data);
 105}
 106
 107void viafb_enable_lvds_vt1636(struct lvds_setting_information
 108                        *plvds_setting_info,
 109                        struct lvds_chip_information *plvds_chip_info)
 110{
 111        viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
 112                vdd_on_data);
 113}
 114
 115void viafb_disable_lvds_vt1636(struct lvds_setting_information
 116                         *plvds_setting_info,
 117                         struct lvds_chip_information *plvds_chip_info)
 118{
 119        viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
 120                vdd_off_data);
 121}
 122
 123bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
 124{
 125        u8 Buffer[2];
 126
 127        DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
 128
 129        /* Sense VT1636 LVDS Transmiter */
 130        viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
 131                VT1636_LVDS_I2C_ADDR;
 132
 133        /* Check vendor ID first: */
 134        if (viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR,
 135                                        0x00, &Buffer[0]))
 136                return false;
 137        viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x01, &Buffer[1]);
 138
 139        if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
 140                return false;
 141
 142        /* Check Chip ID: */
 143        viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x02, &Buffer[0]);
 144        viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x03, &Buffer[1]);
 145        if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
 146                viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
 147                        VT1636_LVDS;
 148                return true;
 149        }
 150
 151        return false;
 152}
 153
 154static int get_clk_range_index(u32 Clk)
 155{
 156        if (Clk < DPA_CLK_30M)
 157                return DPA_CLK_RANGE_30M;
 158        else if (Clk < DPA_CLK_50M)
 159                return DPA_CLK_RANGE_30_50M;
 160        else if (Clk < DPA_CLK_70M)
 161                return DPA_CLK_RANGE_50_70M;
 162        else if (Clk < DPA_CLK_100M)
 163                return DPA_CLK_RANGE_70_100M;
 164        else if (Clk < DPA_CLK_150M)
 165                return DPA_CLK_RANGE_100_150M;
 166        else
 167                return DPA_CLK_RANGE_150M;
 168}
 169
 170static void set_dpa_vt1636(struct lvds_setting_information
 171        *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
 172                    struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
 173{
 174        struct IODATA io_data;
 175
 176        io_data.Index = 0x09;
 177        io_data.Mask = 0x1F;
 178        io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
 179        viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
 180                plvds_chip_info, io_data);
 181
 182        io_data.Index = 0x08;
 183        io_data.Mask = 0x0F;
 184        io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
 185        viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
 186                io_data);
 187}
 188
 189void viafb_vt1636_patch_skew_on_vt3324(
 190        struct lvds_setting_information *plvds_setting_info,
 191        struct lvds_chip_information *plvds_chip_info)
 192{
 193        struct VT1636_DPA_SETTING dpa = {0x00, 0x00}, dpa_16x12 = {0x0B, 0x03},
 194                *pdpa;
 195        int index;
 196
 197        DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
 198
 199        /* Graphics DPA settings: */
 200        index = get_clk_range_index(plvds_setting_info->vclk);
 201        viafb_set_dpa_gfx(plvds_chip_info->output_interface,
 202                    &GFX_DPA_SETTING_TBL_VT3324[index]);
 203
 204        /* LVDS Transmitter DPA settings: */
 205        if (plvds_setting_info->lcd_panel_hres == 1600 &&
 206                plvds_setting_info->lcd_panel_vres == 1200)
 207                pdpa = &dpa_16x12;
 208        else
 209                pdpa = &dpa;
 210
 211        set_dpa_vt1636(plvds_setting_info, plvds_chip_info, pdpa);
 212}
 213
 214void viafb_vt1636_patch_skew_on_vt3327(
 215        struct lvds_setting_information *plvds_setting_info,
 216        struct lvds_chip_information *plvds_chip_info)
 217{
 218        struct VT1636_DPA_SETTING dpa = {0x00, 0x00};
 219        int index;
 220
 221        DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
 222
 223        /* Graphics DPA settings: */
 224        index = get_clk_range_index(plvds_setting_info->vclk);
 225        viafb_set_dpa_gfx(plvds_chip_info->output_interface,
 226                    &GFX_DPA_SETTING_TBL_VT3327[index]);
 227
 228        /* LVDS Transmitter DPA settings: */
 229        set_dpa_vt1636(plvds_setting_info, plvds_chip_info, &dpa);
 230}
 231
 232void viafb_vt1636_patch_skew_on_vt3364(
 233        struct lvds_setting_information *plvds_setting_info,
 234        struct lvds_chip_information *plvds_chip_info)
 235{
 236        int index;
 237
 238        DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
 239
 240        /* Graphics DPA settings: */
 241        index = get_clk_range_index(plvds_setting_info->vclk);
 242        viafb_set_dpa_gfx(plvds_chip_info->output_interface,
 243                    &GFX_DPA_SETTING_TBL_VT3364[index]);
 244}
 245