Back to home page

OSCL-LXR

 
 

    


0001 /**************************************************************************
0002 
0003 Copyright © 2006 Dave Airlie
0004 
0005 All Rights Reserved.
0006 
0007 Permission is hereby granted, free of charge, to any person obtaining a
0008 copy of this software and associated documentation files (the
0009 "Software"), to deal in the Software without restriction, including
0010 without limitation the rights to use, copy, modify, merge, publish,
0011 distribute, sub license, and/or sell copies of the Software, and to
0012 permit persons to whom the Software is furnished to do so, subject to
0013 the following conditions:
0014 
0015 The above copyright notice and this permission notice (including the
0016 next paragraph) shall be included in all copies or substantial portions
0017 of the Software.
0018 
0019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0020 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0021 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
0022 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0023 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
0024 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
0025 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0026 
0027 **************************************************************************/
0028 
0029 #include "intel_display_types.h"
0030 #include "intel_dvo_dev.h"
0031 
0032 #define SIL164_VID 0x0001
0033 #define SIL164_DID 0x0006
0034 
0035 #define SIL164_VID_LO 0x00
0036 #define SIL164_VID_HI 0x01
0037 #define SIL164_DID_LO 0x02
0038 #define SIL164_DID_HI 0x03
0039 #define SIL164_REV    0x04
0040 #define SIL164_RSVD   0x05
0041 #define SIL164_FREQ_LO 0x06
0042 #define SIL164_FREQ_HI 0x07
0043 
0044 #define SIL164_REG8 0x08
0045 #define SIL164_8_VEN (1<<5)
0046 #define SIL164_8_HEN (1<<4)
0047 #define SIL164_8_DSEL (1<<3)
0048 #define SIL164_8_BSEL (1<<2)
0049 #define SIL164_8_EDGE (1<<1)
0050 #define SIL164_8_PD   (1<<0)
0051 
0052 #define SIL164_REG9 0x09
0053 #define SIL164_9_VLOW (1<<7)
0054 #define SIL164_9_MSEL_MASK (0x7<<4)
0055 #define SIL164_9_TSEL (1<<3)
0056 #define SIL164_9_RSEN (1<<2)
0057 #define SIL164_9_HTPLG (1<<1)
0058 #define SIL164_9_MDI (1<<0)
0059 
0060 #define SIL164_REGC 0x0c
0061 
0062 struct sil164_priv {
0063     //I2CDevRec d;
0064     bool quiet;
0065 };
0066 
0067 #define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
0068 
0069 static bool sil164_readb(struct intel_dvo_device *dvo, int addr, u8 *ch)
0070 {
0071     struct sil164_priv *sil = dvo->dev_priv;
0072     struct i2c_adapter *adapter = dvo->i2c_bus;
0073     u8 out_buf[2];
0074     u8 in_buf[2];
0075 
0076     struct i2c_msg msgs[] = {
0077         {
0078             .addr = dvo->slave_addr,
0079             .flags = 0,
0080             .len = 1,
0081             .buf = out_buf,
0082         },
0083         {
0084             .addr = dvo->slave_addr,
0085             .flags = I2C_M_RD,
0086             .len = 1,
0087             .buf = in_buf,
0088         }
0089     };
0090 
0091     out_buf[0] = addr;
0092     out_buf[1] = 0;
0093 
0094     if (i2c_transfer(adapter, msgs, 2) == 2) {
0095         *ch = in_buf[0];
0096         return true;
0097     }
0098 
0099     if (!sil->quiet) {
0100         DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
0101               addr, adapter->name, dvo->slave_addr);
0102     }
0103     return false;
0104 }
0105 
0106 static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, u8 ch)
0107 {
0108     struct sil164_priv *sil = dvo->dev_priv;
0109     struct i2c_adapter *adapter = dvo->i2c_bus;
0110     u8 out_buf[2];
0111     struct i2c_msg msg = {
0112         .addr = dvo->slave_addr,
0113         .flags = 0,
0114         .len = 2,
0115         .buf = out_buf,
0116     };
0117 
0118     out_buf[0] = addr;
0119     out_buf[1] = ch;
0120 
0121     if (i2c_transfer(adapter, &msg, 1) == 1)
0122         return true;
0123 
0124     if (!sil->quiet) {
0125         DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
0126               addr, adapter->name, dvo->slave_addr);
0127     }
0128 
0129     return false;
0130 }
0131 
0132 /* Silicon Image 164 driver for chip on i2c bus */
0133 static bool sil164_init(struct intel_dvo_device *dvo,
0134             struct i2c_adapter *adapter)
0135 {
0136     /* this will detect the SIL164 chip on the specified i2c bus */
0137     struct sil164_priv *sil;
0138     unsigned char ch;
0139 
0140     sil = kzalloc(sizeof(struct sil164_priv), GFP_KERNEL);
0141     if (sil == NULL)
0142         return false;
0143 
0144     dvo->i2c_bus = adapter;
0145     dvo->dev_priv = sil;
0146     sil->quiet = true;
0147 
0148     if (!sil164_readb(dvo, SIL164_VID_LO, &ch))
0149         goto out;
0150 
0151     if (ch != (SIL164_VID & 0xff)) {
0152         DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
0153               ch, adapter->name, dvo->slave_addr);
0154         goto out;
0155     }
0156 
0157     if (!sil164_readb(dvo, SIL164_DID_LO, &ch))
0158         goto out;
0159 
0160     if (ch != (SIL164_DID & 0xff)) {
0161         DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
0162               ch, adapter->name, dvo->slave_addr);
0163         goto out;
0164     }
0165     sil->quiet = false;
0166 
0167     DRM_DEBUG_KMS("init sil164 dvo controller successfully!\n");
0168     return true;
0169 
0170 out:
0171     kfree(sil);
0172     return false;
0173 }
0174 
0175 static enum drm_connector_status sil164_detect(struct intel_dvo_device *dvo)
0176 {
0177     u8 reg9;
0178 
0179     sil164_readb(dvo, SIL164_REG9, &reg9);
0180 
0181     if (reg9 & SIL164_9_HTPLG)
0182         return connector_status_connected;
0183     else
0184         return connector_status_disconnected;
0185 }
0186 
0187 static enum drm_mode_status sil164_mode_valid(struct intel_dvo_device *dvo,
0188                           struct drm_display_mode *mode)
0189 {
0190     return MODE_OK;
0191 }
0192 
0193 static void sil164_mode_set(struct intel_dvo_device *dvo,
0194                 const struct drm_display_mode *mode,
0195                 const struct drm_display_mode *adjusted_mode)
0196 {
0197     /* As long as the basics are set up, since we don't have clock
0198      * dependencies in the mode setup, we can just leave the
0199      * registers alone and everything will work fine.
0200      */
0201     /* recommended programming sequence from doc */
0202     /*sil164_writeb(sil, 0x08, 0x30);
0203       sil164_writeb(sil, 0x09, 0x00);
0204       sil164_writeb(sil, 0x0a, 0x90);
0205       sil164_writeb(sil, 0x0c, 0x89);
0206       sil164_writeb(sil, 0x08, 0x31);*/
0207     /* don't do much */
0208     return;
0209 }
0210 
0211 /* set the SIL164 power state */
0212 static void sil164_dpms(struct intel_dvo_device *dvo, bool enable)
0213 {
0214     int ret;
0215     unsigned char ch;
0216 
0217     ret = sil164_readb(dvo, SIL164_REG8, &ch);
0218     if (ret == false)
0219         return;
0220 
0221     if (enable)
0222         ch |= SIL164_8_PD;
0223     else
0224         ch &= ~SIL164_8_PD;
0225 
0226     sil164_writeb(dvo, SIL164_REG8, ch);
0227     return;
0228 }
0229 
0230 static bool sil164_get_hw_state(struct intel_dvo_device *dvo)
0231 {
0232     int ret;
0233     unsigned char ch;
0234 
0235     ret = sil164_readb(dvo, SIL164_REG8, &ch);
0236     if (ret == false)
0237         return false;
0238 
0239     if (ch & SIL164_8_PD)
0240         return true;
0241     else
0242         return false;
0243 }
0244 
0245 static void sil164_dump_regs(struct intel_dvo_device *dvo)
0246 {
0247     u8 val;
0248 
0249     sil164_readb(dvo, SIL164_FREQ_LO, &val);
0250     DRM_DEBUG_KMS("SIL164_FREQ_LO: 0x%02x\n", val);
0251     sil164_readb(dvo, SIL164_FREQ_HI, &val);
0252     DRM_DEBUG_KMS("SIL164_FREQ_HI: 0x%02x\n", val);
0253     sil164_readb(dvo, SIL164_REG8, &val);
0254     DRM_DEBUG_KMS("SIL164_REG8: 0x%02x\n", val);
0255     sil164_readb(dvo, SIL164_REG9, &val);
0256     DRM_DEBUG_KMS("SIL164_REG9: 0x%02x\n", val);
0257     sil164_readb(dvo, SIL164_REGC, &val);
0258     DRM_DEBUG_KMS("SIL164_REGC: 0x%02x\n", val);
0259 }
0260 
0261 static void sil164_destroy(struct intel_dvo_device *dvo)
0262 {
0263     struct sil164_priv *sil = dvo->dev_priv;
0264 
0265     if (sil) {
0266         kfree(sil);
0267         dvo->dev_priv = NULL;
0268     }
0269 }
0270 
0271 const struct intel_dvo_dev_ops sil164_ops = {
0272     .init = sil164_init,
0273     .detect = sil164_detect,
0274     .mode_valid = sil164_mode_valid,
0275     .mode_set = sil164_mode_set,
0276     .dpms = sil164_dpms,
0277     .get_hw_state = sil164_get_hw_state,
0278     .dump_regs = sil164_dump_regs,
0279     .destroy = sil164_destroy,
0280 };