1 1.1 riastrad /* $NetBSD: dvo_sil164.c,v 1.2 2021/12/18 23:45:29 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /************************************************************************** 4 1.1 riastrad 5 1.1 riastrad Copyright 2006 Dave Airlie 6 1.1 riastrad 7 1.1 riastrad All Rights Reserved. 8 1.1 riastrad 9 1.1 riastrad Permission is hereby granted, free of charge, to any person obtaining a 10 1.1 riastrad copy of this software and associated documentation files (the 11 1.1 riastrad "Software"), to deal in the Software without restriction, including 12 1.1 riastrad without limitation the rights to use, copy, modify, merge, publish, 13 1.1 riastrad distribute, sub license, and/or sell copies of the Software, and to 14 1.1 riastrad permit persons to whom the Software is furnished to do so, subject to 15 1.1 riastrad the following conditions: 16 1.1 riastrad 17 1.1 riastrad The above copyright notice and this permission notice (including the 18 1.1 riastrad next paragraph) shall be included in all copies or substantial portions 19 1.1 riastrad of the Software. 20 1.1 riastrad 21 1.1 riastrad THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22 1.1 riastrad OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 1.1 riastrad MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 24 1.1 riastrad IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 25 1.1 riastrad ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 1.1 riastrad TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 1.1 riastrad SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 1.1 riastrad 29 1.1 riastrad **************************************************************************/ 30 1.1 riastrad 31 1.1 riastrad #include <sys/cdefs.h> 32 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: dvo_sil164.c,v 1.2 2021/12/18 23:45:29 riastradh Exp $"); 33 1.1 riastrad 34 1.1 riastrad #include "intel_display_types.h" 35 1.1 riastrad #include "intel_dvo_dev.h" 36 1.1 riastrad 37 1.1 riastrad #define SIL164_VID 0x0001 38 1.1 riastrad #define SIL164_DID 0x0006 39 1.1 riastrad 40 1.1 riastrad #define SIL164_VID_LO 0x00 41 1.1 riastrad #define SIL164_VID_HI 0x01 42 1.1 riastrad #define SIL164_DID_LO 0x02 43 1.1 riastrad #define SIL164_DID_HI 0x03 44 1.1 riastrad #define SIL164_REV 0x04 45 1.1 riastrad #define SIL164_RSVD 0x05 46 1.1 riastrad #define SIL164_FREQ_LO 0x06 47 1.1 riastrad #define SIL164_FREQ_HI 0x07 48 1.1 riastrad 49 1.1 riastrad #define SIL164_REG8 0x08 50 1.1 riastrad #define SIL164_8_VEN (1<<5) 51 1.1 riastrad #define SIL164_8_HEN (1<<4) 52 1.1 riastrad #define SIL164_8_DSEL (1<<3) 53 1.1 riastrad #define SIL164_8_BSEL (1<<2) 54 1.1 riastrad #define SIL164_8_EDGE (1<<1) 55 1.1 riastrad #define SIL164_8_PD (1<<0) 56 1.1 riastrad 57 1.1 riastrad #define SIL164_REG9 0x09 58 1.1 riastrad #define SIL164_9_VLOW (1<<7) 59 1.1 riastrad #define SIL164_9_MSEL_MASK (0x7<<4) 60 1.1 riastrad #define SIL164_9_TSEL (1<<3) 61 1.1 riastrad #define SIL164_9_RSEN (1<<2) 62 1.1 riastrad #define SIL164_9_HTPLG (1<<1) 63 1.1 riastrad #define SIL164_9_MDI (1<<0) 64 1.1 riastrad 65 1.1 riastrad #define SIL164_REGC 0x0c 66 1.1 riastrad 67 1.1 riastrad struct sil164_priv { 68 1.1 riastrad //I2CDevRec d; 69 1.1 riastrad bool quiet; 70 1.1 riastrad }; 71 1.1 riastrad 72 1.1 riastrad #define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr)) 73 1.1 riastrad 74 1.1 riastrad static bool sil164_readb(struct intel_dvo_device *dvo, int addr, u8 *ch) 75 1.1 riastrad { 76 1.1 riastrad struct sil164_priv *sil = dvo->dev_priv; 77 1.1 riastrad struct i2c_adapter *adapter = dvo->i2c_bus; 78 1.1 riastrad u8 out_buf[2]; 79 1.1 riastrad u8 in_buf[2]; 80 1.1 riastrad 81 1.1 riastrad struct i2c_msg msgs[] = { 82 1.1 riastrad { 83 1.1 riastrad .addr = dvo->slave_addr, 84 1.1 riastrad .flags = 0, 85 1.1 riastrad .len = 1, 86 1.1 riastrad .buf = out_buf, 87 1.1 riastrad }, 88 1.1 riastrad { 89 1.1 riastrad .addr = dvo->slave_addr, 90 1.1 riastrad .flags = I2C_M_RD, 91 1.1 riastrad .len = 1, 92 1.1 riastrad .buf = in_buf, 93 1.1 riastrad } 94 1.1 riastrad }; 95 1.1 riastrad 96 1.1 riastrad out_buf[0] = addr; 97 1.1 riastrad out_buf[1] = 0; 98 1.1 riastrad 99 1.1 riastrad if (i2c_transfer(adapter, msgs, 2) == 2) { 100 1.1 riastrad *ch = in_buf[0]; 101 1.1 riastrad return true; 102 1.1 riastrad } 103 1.1 riastrad 104 1.1 riastrad if (!sil->quiet) { 105 1.1 riastrad DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", 106 1.1 riastrad addr, adapter->name, dvo->slave_addr); 107 1.1 riastrad } 108 1.1 riastrad return false; 109 1.1 riastrad } 110 1.1 riastrad 111 1.1 riastrad static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, u8 ch) 112 1.1 riastrad { 113 1.1 riastrad struct sil164_priv *sil = dvo->dev_priv; 114 1.1 riastrad struct i2c_adapter *adapter = dvo->i2c_bus; 115 1.1 riastrad u8 out_buf[2]; 116 1.1 riastrad struct i2c_msg msg = { 117 1.1 riastrad .addr = dvo->slave_addr, 118 1.1 riastrad .flags = 0, 119 1.1 riastrad .len = 2, 120 1.1 riastrad .buf = out_buf, 121 1.1 riastrad }; 122 1.1 riastrad 123 1.1 riastrad out_buf[0] = addr; 124 1.1 riastrad out_buf[1] = ch; 125 1.1 riastrad 126 1.1 riastrad if (i2c_transfer(adapter, &msg, 1) == 1) 127 1.1 riastrad return true; 128 1.1 riastrad 129 1.1 riastrad if (!sil->quiet) { 130 1.1 riastrad DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", 131 1.1 riastrad addr, adapter->name, dvo->slave_addr); 132 1.1 riastrad } 133 1.1 riastrad 134 1.1 riastrad return false; 135 1.1 riastrad } 136 1.1 riastrad 137 1.1 riastrad /* Silicon Image 164 driver for chip on i2c bus */ 138 1.1 riastrad static bool sil164_init(struct intel_dvo_device *dvo, 139 1.1 riastrad struct i2c_adapter *adapter) 140 1.1 riastrad { 141 1.1 riastrad /* this will detect the SIL164 chip on the specified i2c bus */ 142 1.1 riastrad struct sil164_priv *sil; 143 1.1 riastrad unsigned char ch; 144 1.1 riastrad 145 1.1 riastrad sil = kzalloc(sizeof(struct sil164_priv), GFP_KERNEL); 146 1.1 riastrad if (sil == NULL) 147 1.1 riastrad return false; 148 1.1 riastrad 149 1.1 riastrad dvo->i2c_bus = adapter; 150 1.1 riastrad dvo->dev_priv = sil; 151 1.1 riastrad sil->quiet = true; 152 1.1 riastrad 153 1.1 riastrad if (!sil164_readb(dvo, SIL164_VID_LO, &ch)) 154 1.1 riastrad goto out; 155 1.1 riastrad 156 1.1 riastrad if (ch != (SIL164_VID & 0xff)) { 157 1.1 riastrad DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n", 158 1.1 riastrad ch, adapter->name, dvo->slave_addr); 159 1.1 riastrad goto out; 160 1.1 riastrad } 161 1.1 riastrad 162 1.1 riastrad if (!sil164_readb(dvo, SIL164_DID_LO, &ch)) 163 1.1 riastrad goto out; 164 1.1 riastrad 165 1.1 riastrad if (ch != (SIL164_DID & 0xff)) { 166 1.1 riastrad DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n", 167 1.1 riastrad ch, adapter->name, dvo->slave_addr); 168 1.1 riastrad goto out; 169 1.1 riastrad } 170 1.1 riastrad sil->quiet = false; 171 1.1 riastrad 172 1.1 riastrad DRM_DEBUG_KMS("init sil164 dvo controller successfully!\n"); 173 1.1 riastrad return true; 174 1.1 riastrad 175 1.1 riastrad out: 176 1.1 riastrad kfree(sil); 177 1.1 riastrad return false; 178 1.1 riastrad } 179 1.1 riastrad 180 1.1 riastrad static enum drm_connector_status sil164_detect(struct intel_dvo_device *dvo) 181 1.1 riastrad { 182 1.1 riastrad u8 reg9; 183 1.1 riastrad 184 1.1 riastrad sil164_readb(dvo, SIL164_REG9, ®9); 185 1.1 riastrad 186 1.1 riastrad if (reg9 & SIL164_9_HTPLG) 187 1.1 riastrad return connector_status_connected; 188 1.1 riastrad else 189 1.1 riastrad return connector_status_disconnected; 190 1.1 riastrad } 191 1.1 riastrad 192 1.1 riastrad static enum drm_mode_status sil164_mode_valid(struct intel_dvo_device *dvo, 193 1.1 riastrad struct drm_display_mode *mode) 194 1.1 riastrad { 195 1.1 riastrad return MODE_OK; 196 1.1 riastrad } 197 1.1 riastrad 198 1.1 riastrad static void sil164_mode_set(struct intel_dvo_device *dvo, 199 1.1 riastrad const struct drm_display_mode *mode, 200 1.1 riastrad const struct drm_display_mode *adjusted_mode) 201 1.1 riastrad { 202 1.1 riastrad /* As long as the basics are set up, since we don't have clock 203 1.1 riastrad * dependencies in the mode setup, we can just leave the 204 1.1 riastrad * registers alone and everything will work fine. 205 1.1 riastrad */ 206 1.1 riastrad /* recommended programming sequence from doc */ 207 1.1 riastrad /*sil164_writeb(sil, 0x08, 0x30); 208 1.1 riastrad sil164_writeb(sil, 0x09, 0x00); 209 1.1 riastrad sil164_writeb(sil, 0x0a, 0x90); 210 1.1 riastrad sil164_writeb(sil, 0x0c, 0x89); 211 1.1 riastrad sil164_writeb(sil, 0x08, 0x31);*/ 212 1.1 riastrad /* don't do much */ 213 1.1 riastrad return; 214 1.1 riastrad } 215 1.1 riastrad 216 1.1 riastrad /* set the SIL164 power state */ 217 1.1 riastrad static void sil164_dpms(struct intel_dvo_device *dvo, bool enable) 218 1.1 riastrad { 219 1.1 riastrad int ret; 220 1.1 riastrad unsigned char ch; 221 1.1 riastrad 222 1.1 riastrad ret = sil164_readb(dvo, SIL164_REG8, &ch); 223 1.1 riastrad if (ret == false) 224 1.1 riastrad return; 225 1.1 riastrad 226 1.1 riastrad if (enable) 227 1.1 riastrad ch |= SIL164_8_PD; 228 1.1 riastrad else 229 1.1 riastrad ch &= ~SIL164_8_PD; 230 1.1 riastrad 231 1.1 riastrad sil164_writeb(dvo, SIL164_REG8, ch); 232 1.1 riastrad return; 233 1.1 riastrad } 234 1.1 riastrad 235 1.1 riastrad static bool sil164_get_hw_state(struct intel_dvo_device *dvo) 236 1.1 riastrad { 237 1.1 riastrad int ret; 238 1.1 riastrad unsigned char ch; 239 1.1 riastrad 240 1.1 riastrad ret = sil164_readb(dvo, SIL164_REG8, &ch); 241 1.1 riastrad if (ret == false) 242 1.1 riastrad return false; 243 1.1 riastrad 244 1.1 riastrad if (ch & SIL164_8_PD) 245 1.1 riastrad return true; 246 1.1 riastrad else 247 1.1 riastrad return false; 248 1.1 riastrad } 249 1.1 riastrad 250 1.1 riastrad static void sil164_dump_regs(struct intel_dvo_device *dvo) 251 1.1 riastrad { 252 1.1 riastrad u8 val; 253 1.1 riastrad 254 1.1 riastrad sil164_readb(dvo, SIL164_FREQ_LO, &val); 255 1.1 riastrad DRM_DEBUG_KMS("SIL164_FREQ_LO: 0x%02x\n", val); 256 1.1 riastrad sil164_readb(dvo, SIL164_FREQ_HI, &val); 257 1.1 riastrad DRM_DEBUG_KMS("SIL164_FREQ_HI: 0x%02x\n", val); 258 1.1 riastrad sil164_readb(dvo, SIL164_REG8, &val); 259 1.1 riastrad DRM_DEBUG_KMS("SIL164_REG8: 0x%02x\n", val); 260 1.1 riastrad sil164_readb(dvo, SIL164_REG9, &val); 261 1.1 riastrad DRM_DEBUG_KMS("SIL164_REG9: 0x%02x\n", val); 262 1.1 riastrad sil164_readb(dvo, SIL164_REGC, &val); 263 1.1 riastrad DRM_DEBUG_KMS("SIL164_REGC: 0x%02x\n", val); 264 1.1 riastrad } 265 1.1 riastrad 266 1.1 riastrad static void sil164_destroy(struct intel_dvo_device *dvo) 267 1.1 riastrad { 268 1.1 riastrad struct sil164_priv *sil = dvo->dev_priv; 269 1.1 riastrad 270 1.1 riastrad if (sil) { 271 1.1 riastrad kfree(sil); 272 1.1 riastrad dvo->dev_priv = NULL; 273 1.1 riastrad } 274 1.1 riastrad } 275 1.1 riastrad 276 1.1 riastrad const struct intel_dvo_dev_ops sil164_ops = { 277 1.1 riastrad .init = sil164_init, 278 1.1 riastrad .detect = sil164_detect, 279 1.1 riastrad .mode_valid = sil164_mode_valid, 280 1.1 riastrad .mode_set = sil164_mode_set, 281 1.1 riastrad .dpms = sil164_dpms, 282 1.1 riastrad .get_hw_state = sil164_get_hw_state, 283 1.1 riastrad .dump_regs = sil164_dump_regs, 284 1.1 riastrad .destroy = sil164_destroy, 285 1.1 riastrad }; 286