1*fb4d8502Sjsg /* 2*fb4d8502Sjsg * Copyright 2007-8 Advanced Micro Devices, Inc. 3*fb4d8502Sjsg * Copyright 2008 Red Hat Inc. 4*fb4d8502Sjsg * 5*fb4d8502Sjsg * Permission is hereby granted, free of charge, to any person obtaining a 6*fb4d8502Sjsg * copy of this software and associated documentation files (the "Software"), 7*fb4d8502Sjsg * to deal in the Software without restriction, including without limitation 8*fb4d8502Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9*fb4d8502Sjsg * and/or sell copies of the Software, and to permit persons to whom the 10*fb4d8502Sjsg * Software is furnished to do so, subject to the following conditions: 11*fb4d8502Sjsg * 12*fb4d8502Sjsg * The above copyright notice and this permission notice shall be included in 13*fb4d8502Sjsg * all copies or substantial portions of the Software. 14*fb4d8502Sjsg * 15*fb4d8502Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*fb4d8502Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*fb4d8502Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*fb4d8502Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19*fb4d8502Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20*fb4d8502Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21*fb4d8502Sjsg * OTHER DEALINGS IN THE SOFTWARE. 22*fb4d8502Sjsg * 23*fb4d8502Sjsg * Authors: Dave Airlie 24*fb4d8502Sjsg * Alex Deucher 25*fb4d8502Sjsg */ 26*fb4d8502Sjsg #include <linux/export.h> 27*fb4d8502Sjsg 28*fb4d8502Sjsg #include <drm/drmP.h> 29*fb4d8502Sjsg #include <drm/drm_edid.h> 30*fb4d8502Sjsg #include <drm/amdgpu_drm.h> 31*fb4d8502Sjsg #include "amdgpu.h" 32*fb4d8502Sjsg #include "amdgpu_i2c.h" 33*fb4d8502Sjsg #include "amdgpu_atombios.h" 34*fb4d8502Sjsg #include "atom.h" 35*fb4d8502Sjsg #include "atombios_dp.h" 36*fb4d8502Sjsg #include "atombios_i2c.h" 37*fb4d8502Sjsg 38*fb4d8502Sjsg #include <dev/i2c/i2cvar.h> 39*fb4d8502Sjsg #include <dev/i2c/i2c_bitbang.h> 40*fb4d8502Sjsg 41*fb4d8502Sjsg /* bit banging i2c */ 42*fb4d8502Sjsg static int amdgpu_i2c_pre_xfer(struct i2c_adapter *i2c_adap) 43*fb4d8502Sjsg { 44*fb4d8502Sjsg struct amdgpu_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); 45*fb4d8502Sjsg struct amdgpu_device *adev = i2c->dev->dev_private; 46*fb4d8502Sjsg struct amdgpu_i2c_bus_rec *rec = &i2c->rec; 47*fb4d8502Sjsg uint32_t temp; 48*fb4d8502Sjsg 49*fb4d8502Sjsg mutex_lock(&i2c->mutex); 50*fb4d8502Sjsg 51*fb4d8502Sjsg /* switch the pads to ddc mode */ 52*fb4d8502Sjsg if (rec->hw_capable) { 53*fb4d8502Sjsg temp = RREG32(rec->mask_clk_reg); 54*fb4d8502Sjsg temp &= ~(1 << 16); 55*fb4d8502Sjsg WREG32(rec->mask_clk_reg, temp); 56*fb4d8502Sjsg } 57*fb4d8502Sjsg 58*fb4d8502Sjsg /* clear the output pin values */ 59*fb4d8502Sjsg temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask; 60*fb4d8502Sjsg WREG32(rec->a_clk_reg, temp); 61*fb4d8502Sjsg 62*fb4d8502Sjsg temp = RREG32(rec->a_data_reg) & ~rec->a_data_mask; 63*fb4d8502Sjsg WREG32(rec->a_data_reg, temp); 64*fb4d8502Sjsg 65*fb4d8502Sjsg /* set the pins to input */ 66*fb4d8502Sjsg temp = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask; 67*fb4d8502Sjsg WREG32(rec->en_clk_reg, temp); 68*fb4d8502Sjsg 69*fb4d8502Sjsg temp = RREG32(rec->en_data_reg) & ~rec->en_data_mask; 70*fb4d8502Sjsg WREG32(rec->en_data_reg, temp); 71*fb4d8502Sjsg 72*fb4d8502Sjsg /* mask the gpio pins for software use */ 73*fb4d8502Sjsg temp = RREG32(rec->mask_clk_reg) | rec->mask_clk_mask; 74*fb4d8502Sjsg WREG32(rec->mask_clk_reg, temp); 75*fb4d8502Sjsg temp = RREG32(rec->mask_clk_reg); 76*fb4d8502Sjsg 77*fb4d8502Sjsg temp = RREG32(rec->mask_data_reg) | rec->mask_data_mask; 78*fb4d8502Sjsg WREG32(rec->mask_data_reg, temp); 79*fb4d8502Sjsg temp = RREG32(rec->mask_data_reg); 80*fb4d8502Sjsg 81*fb4d8502Sjsg return 0; 82*fb4d8502Sjsg } 83*fb4d8502Sjsg 84*fb4d8502Sjsg static void amdgpu_i2c_post_xfer(struct i2c_adapter *i2c_adap) 85*fb4d8502Sjsg { 86*fb4d8502Sjsg struct amdgpu_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); 87*fb4d8502Sjsg struct amdgpu_device *adev = i2c->dev->dev_private; 88*fb4d8502Sjsg struct amdgpu_i2c_bus_rec *rec = &i2c->rec; 89*fb4d8502Sjsg uint32_t temp; 90*fb4d8502Sjsg 91*fb4d8502Sjsg /* unmask the gpio pins for software use */ 92*fb4d8502Sjsg temp = RREG32(rec->mask_clk_reg) & ~rec->mask_clk_mask; 93*fb4d8502Sjsg WREG32(rec->mask_clk_reg, temp); 94*fb4d8502Sjsg temp = RREG32(rec->mask_clk_reg); 95*fb4d8502Sjsg 96*fb4d8502Sjsg temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask; 97*fb4d8502Sjsg WREG32(rec->mask_data_reg, temp); 98*fb4d8502Sjsg temp = RREG32(rec->mask_data_reg); 99*fb4d8502Sjsg 100*fb4d8502Sjsg mutex_unlock(&i2c->mutex); 101*fb4d8502Sjsg } 102*fb4d8502Sjsg 103*fb4d8502Sjsg static int amdgpu_i2c_get_clock(void *i2c_priv) 104*fb4d8502Sjsg { 105*fb4d8502Sjsg struct amdgpu_i2c_chan *i2c = i2c_priv; 106*fb4d8502Sjsg struct amdgpu_device *adev = i2c->dev->dev_private; 107*fb4d8502Sjsg struct amdgpu_i2c_bus_rec *rec = &i2c->rec; 108*fb4d8502Sjsg uint32_t val; 109*fb4d8502Sjsg 110*fb4d8502Sjsg /* read the value off the pin */ 111*fb4d8502Sjsg val = RREG32(rec->y_clk_reg); 112*fb4d8502Sjsg val &= rec->y_clk_mask; 113*fb4d8502Sjsg 114*fb4d8502Sjsg return (val != 0); 115*fb4d8502Sjsg } 116*fb4d8502Sjsg 117*fb4d8502Sjsg 118*fb4d8502Sjsg static int amdgpu_i2c_get_data(void *i2c_priv) 119*fb4d8502Sjsg { 120*fb4d8502Sjsg struct amdgpu_i2c_chan *i2c = i2c_priv; 121*fb4d8502Sjsg struct amdgpu_device *adev = i2c->dev->dev_private; 122*fb4d8502Sjsg struct amdgpu_i2c_bus_rec *rec = &i2c->rec; 123*fb4d8502Sjsg uint32_t val; 124*fb4d8502Sjsg 125*fb4d8502Sjsg /* read the value off the pin */ 126*fb4d8502Sjsg val = RREG32(rec->y_data_reg); 127*fb4d8502Sjsg val &= rec->y_data_mask; 128*fb4d8502Sjsg 129*fb4d8502Sjsg return (val != 0); 130*fb4d8502Sjsg } 131*fb4d8502Sjsg 132*fb4d8502Sjsg static void amdgpu_i2c_set_clock(void *i2c_priv, int clock) 133*fb4d8502Sjsg { 134*fb4d8502Sjsg struct amdgpu_i2c_chan *i2c = i2c_priv; 135*fb4d8502Sjsg struct amdgpu_device *adev = i2c->dev->dev_private; 136*fb4d8502Sjsg struct amdgpu_i2c_bus_rec *rec = &i2c->rec; 137*fb4d8502Sjsg uint32_t val; 138*fb4d8502Sjsg 139*fb4d8502Sjsg /* set pin direction */ 140*fb4d8502Sjsg val = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask; 141*fb4d8502Sjsg val |= clock ? 0 : rec->en_clk_mask; 142*fb4d8502Sjsg WREG32(rec->en_clk_reg, val); 143*fb4d8502Sjsg } 144*fb4d8502Sjsg 145*fb4d8502Sjsg static void amdgpu_i2c_set_data(void *i2c_priv, int data) 146*fb4d8502Sjsg { 147*fb4d8502Sjsg struct amdgpu_i2c_chan *i2c = i2c_priv; 148*fb4d8502Sjsg struct amdgpu_device *adev = i2c->dev->dev_private; 149*fb4d8502Sjsg struct amdgpu_i2c_bus_rec *rec = &i2c->rec; 150*fb4d8502Sjsg uint32_t val; 151*fb4d8502Sjsg 152*fb4d8502Sjsg /* set pin direction */ 153*fb4d8502Sjsg val = RREG32(rec->en_data_reg) & ~rec->en_data_mask; 154*fb4d8502Sjsg val |= data ? 0 : rec->en_data_mask; 155*fb4d8502Sjsg WREG32(rec->en_data_reg, val); 156*fb4d8502Sjsg } 157*fb4d8502Sjsg 158*fb4d8502Sjsg void amdgpu_bb_set_bits(void *, uint32_t); 159*fb4d8502Sjsg void amdgpu_bb_set_dir(void *, uint32_t); 160*fb4d8502Sjsg uint32_t amdgpu_bb_read_bits(void *); 161*fb4d8502Sjsg 162*fb4d8502Sjsg int amdgpu_acquire_bus(void *, int); 163*fb4d8502Sjsg void amdgpu_release_bus(void *, int); 164*fb4d8502Sjsg int amdgpu_send_start(void *, int); 165*fb4d8502Sjsg int amdgpu_send_stop(void *, int); 166*fb4d8502Sjsg int amdgpu_initiate_xfer(void *, i2c_addr_t, int); 167*fb4d8502Sjsg int amdgpu_read_byte(void *, u_int8_t *, int); 168*fb4d8502Sjsg int amdgpu_write_byte(void *, u_int8_t, int); 169*fb4d8502Sjsg 170*fb4d8502Sjsg #define AMDGPU_BB_SDA (1 << I2C_BIT_SDA) 171*fb4d8502Sjsg #define AMDGPU_BB_SCL (1 << I2C_BIT_SCL) 172*fb4d8502Sjsg 173*fb4d8502Sjsg struct i2c_bitbang_ops amdgpu_bbops = { 174*fb4d8502Sjsg amdgpu_bb_set_bits, 175*fb4d8502Sjsg amdgpu_bb_set_dir, 176*fb4d8502Sjsg amdgpu_bb_read_bits, 177*fb4d8502Sjsg { AMDGPU_BB_SDA, AMDGPU_BB_SCL, 0, 0 } 178*fb4d8502Sjsg }; 179*fb4d8502Sjsg 180*fb4d8502Sjsg void 181*fb4d8502Sjsg amdgpu_bb_set_bits(void *cookie, uint32_t bits) 182*fb4d8502Sjsg { 183*fb4d8502Sjsg amdgpu_i2c_set_clock(cookie, bits & AMDGPU_BB_SCL); 184*fb4d8502Sjsg amdgpu_i2c_set_data(cookie, bits & AMDGPU_BB_SDA); 185*fb4d8502Sjsg } 186*fb4d8502Sjsg 187*fb4d8502Sjsg void 188*fb4d8502Sjsg amdgpu_bb_set_dir(void *cookie, uint32_t bits) 189*fb4d8502Sjsg { 190*fb4d8502Sjsg } 191*fb4d8502Sjsg 192*fb4d8502Sjsg uint32_t 193*fb4d8502Sjsg amdgpu_bb_read_bits(void *cookie) 194*fb4d8502Sjsg { 195*fb4d8502Sjsg uint32_t bits = 0; 196*fb4d8502Sjsg 197*fb4d8502Sjsg if (amdgpu_i2c_get_clock(cookie)) 198*fb4d8502Sjsg bits |= AMDGPU_BB_SCL; 199*fb4d8502Sjsg if (amdgpu_i2c_get_data(cookie)) 200*fb4d8502Sjsg bits |= AMDGPU_BB_SDA; 201*fb4d8502Sjsg 202*fb4d8502Sjsg return bits; 203*fb4d8502Sjsg } 204*fb4d8502Sjsg 205*fb4d8502Sjsg int 206*fb4d8502Sjsg amdgpu_acquire_bus(void *cookie, int flags) 207*fb4d8502Sjsg { 208*fb4d8502Sjsg struct amdgpu_i2c_chan *i2c = cookie; 209*fb4d8502Sjsg amdgpu_i2c_pre_xfer(&i2c->adapter); 210*fb4d8502Sjsg return (0); 211*fb4d8502Sjsg } 212*fb4d8502Sjsg 213*fb4d8502Sjsg void 214*fb4d8502Sjsg amdgpu_release_bus(void *cookie, int flags) 215*fb4d8502Sjsg { 216*fb4d8502Sjsg struct amdgpu_i2c_chan *i2c = cookie; 217*fb4d8502Sjsg amdgpu_i2c_post_xfer(&i2c->adapter); 218*fb4d8502Sjsg } 219*fb4d8502Sjsg 220*fb4d8502Sjsg int 221*fb4d8502Sjsg amdgpu_send_start(void *cookie, int flags) 222*fb4d8502Sjsg { 223*fb4d8502Sjsg return (i2c_bitbang_send_start(cookie, flags, &amdgpu_bbops)); 224*fb4d8502Sjsg } 225*fb4d8502Sjsg 226*fb4d8502Sjsg int 227*fb4d8502Sjsg amdgpu_send_stop(void *cookie, int flags) 228*fb4d8502Sjsg { 229*fb4d8502Sjsg return (i2c_bitbang_send_stop(cookie, flags, &amdgpu_bbops)); 230*fb4d8502Sjsg } 231*fb4d8502Sjsg 232*fb4d8502Sjsg int 233*fb4d8502Sjsg amdgpu_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) 234*fb4d8502Sjsg { 235*fb4d8502Sjsg return (i2c_bitbang_initiate_xfer(cookie, addr, flags, &amdgpu_bbops)); 236*fb4d8502Sjsg } 237*fb4d8502Sjsg 238*fb4d8502Sjsg int 239*fb4d8502Sjsg amdgpu_read_byte(void *cookie, u_int8_t *bytep, int flags) 240*fb4d8502Sjsg { 241*fb4d8502Sjsg return (i2c_bitbang_read_byte(cookie, bytep, flags, &amdgpu_bbops)); 242*fb4d8502Sjsg } 243*fb4d8502Sjsg 244*fb4d8502Sjsg int 245*fb4d8502Sjsg amdgpu_write_byte(void *cookie, u_int8_t byte, int flags) 246*fb4d8502Sjsg { 247*fb4d8502Sjsg return (i2c_bitbang_write_byte(cookie, byte, flags, &amdgpu_bbops)); 248*fb4d8502Sjsg } 249*fb4d8502Sjsg 250*fb4d8502Sjsg static const struct i2c_algorithm amdgpu_atombios_i2c_algo = { 251*fb4d8502Sjsg .master_xfer = amdgpu_atombios_i2c_xfer, 252*fb4d8502Sjsg .functionality = amdgpu_atombios_i2c_func, 253*fb4d8502Sjsg }; 254*fb4d8502Sjsg 255*fb4d8502Sjsg struct amdgpu_i2c_chan *amdgpu_i2c_create(struct drm_device *dev, 256*fb4d8502Sjsg const struct amdgpu_i2c_bus_rec *rec, 257*fb4d8502Sjsg const char *name) 258*fb4d8502Sjsg { 259*fb4d8502Sjsg struct amdgpu_i2c_chan *i2c; 260*fb4d8502Sjsg int ret; 261*fb4d8502Sjsg 262*fb4d8502Sjsg /* don't add the mm_i2c bus unless hw_i2c is enabled */ 263*fb4d8502Sjsg if (rec->mm_i2c && (amdgpu_hw_i2c == 0)) 264*fb4d8502Sjsg return NULL; 265*fb4d8502Sjsg 266*fb4d8502Sjsg i2c = kzalloc(sizeof(struct amdgpu_i2c_chan), GFP_KERNEL); 267*fb4d8502Sjsg if (i2c == NULL) 268*fb4d8502Sjsg return NULL; 269*fb4d8502Sjsg 270*fb4d8502Sjsg i2c->rec = *rec; 271*fb4d8502Sjsg #ifdef __linux__ 272*fb4d8502Sjsg i2c->adapter.owner = THIS_MODULE; 273*fb4d8502Sjsg i2c->adapter.class = I2C_CLASS_DDC; 274*fb4d8502Sjsg i2c->adapter.dev.parent = &dev->pdev->dev; 275*fb4d8502Sjsg #endif 276*fb4d8502Sjsg i2c->dev = dev; 277*fb4d8502Sjsg i2c_set_adapdata(&i2c->adapter, i2c); 278*fb4d8502Sjsg rw_init(&i2c->mutex, "agiic"); 279*fb4d8502Sjsg if (rec->hw_capable && 280*fb4d8502Sjsg amdgpu_hw_i2c) { 281*fb4d8502Sjsg /* hw i2c using atom */ 282*fb4d8502Sjsg snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), 283*fb4d8502Sjsg "AMDGPU i2c hw bus %s", name); 284*fb4d8502Sjsg i2c->adapter.algo = &amdgpu_atombios_i2c_algo; 285*fb4d8502Sjsg ret = i2c_add_adapter(&i2c->adapter); 286*fb4d8502Sjsg if (ret) 287*fb4d8502Sjsg goto out_free; 288*fb4d8502Sjsg } else { 289*fb4d8502Sjsg /* set the amdgpu bit adapter */ 290*fb4d8502Sjsg snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), 291*fb4d8502Sjsg "AMDGPU i2c bit bus %s", name); 292*fb4d8502Sjsg i2c->adapter.algo_data = &i2c->bit; 293*fb4d8502Sjsg #ifdef notyet 294*fb4d8502Sjsg i2c->bit.pre_xfer = amdgpu_i2c_pre_xfer; 295*fb4d8502Sjsg i2c->bit.post_xfer = amdgpu_i2c_post_xfer; 296*fb4d8502Sjsg i2c->bit.setsda = amdgpu_i2c_set_data; 297*fb4d8502Sjsg i2c->bit.setscl = amdgpu_i2c_set_clock; 298*fb4d8502Sjsg i2c->bit.getsda = amdgpu_i2c_get_data; 299*fb4d8502Sjsg i2c->bit.getscl = amdgpu_i2c_get_clock; 300*fb4d8502Sjsg i2c->bit.udelay = 10; 301*fb4d8502Sjsg i2c->bit.timeout = usecs_to_jiffies(2200); /* from VESA */ 302*fb4d8502Sjsg i2c->bit.data = i2c; 303*fb4d8502Sjsg #else 304*fb4d8502Sjsg i2c->bit.ic.ic_cookie = i2c; 305*fb4d8502Sjsg i2c->bit.ic.ic_acquire_bus = amdgpu_acquire_bus; 306*fb4d8502Sjsg i2c->bit.ic.ic_release_bus = amdgpu_release_bus; 307*fb4d8502Sjsg i2c->bit.ic.ic_send_start = amdgpu_send_start; 308*fb4d8502Sjsg i2c->bit.ic.ic_send_stop = amdgpu_send_stop; 309*fb4d8502Sjsg i2c->bit.ic.ic_initiate_xfer = amdgpu_initiate_xfer; 310*fb4d8502Sjsg i2c->bit.ic.ic_read_byte = amdgpu_read_byte; 311*fb4d8502Sjsg i2c->bit.ic.ic_write_byte = amdgpu_write_byte; 312*fb4d8502Sjsg #endif 313*fb4d8502Sjsg ret = i2c_bit_add_bus(&i2c->adapter); 314*fb4d8502Sjsg if (ret) { 315*fb4d8502Sjsg DRM_ERROR("Failed to register bit i2c %s\n", name); 316*fb4d8502Sjsg goto out_free; 317*fb4d8502Sjsg } 318*fb4d8502Sjsg } 319*fb4d8502Sjsg 320*fb4d8502Sjsg return i2c; 321*fb4d8502Sjsg out_free: 322*fb4d8502Sjsg kfree(i2c); 323*fb4d8502Sjsg return NULL; 324*fb4d8502Sjsg 325*fb4d8502Sjsg } 326*fb4d8502Sjsg 327*fb4d8502Sjsg void amdgpu_i2c_destroy(struct amdgpu_i2c_chan *i2c) 328*fb4d8502Sjsg { 329*fb4d8502Sjsg if (!i2c) 330*fb4d8502Sjsg return; 331*fb4d8502Sjsg WARN_ON(i2c->has_aux); 332*fb4d8502Sjsg i2c_del_adapter(&i2c->adapter); 333*fb4d8502Sjsg kfree(i2c); 334*fb4d8502Sjsg } 335*fb4d8502Sjsg 336*fb4d8502Sjsg /* Add the default buses */ 337*fb4d8502Sjsg void amdgpu_i2c_init(struct amdgpu_device *adev) 338*fb4d8502Sjsg { 339*fb4d8502Sjsg if (amdgpu_hw_i2c) 340*fb4d8502Sjsg DRM_INFO("hw_i2c forced on, you may experience display detection problems!\n"); 341*fb4d8502Sjsg 342*fb4d8502Sjsg amdgpu_atombios_i2c_init(adev); 343*fb4d8502Sjsg } 344*fb4d8502Sjsg 345*fb4d8502Sjsg /* remove all the buses */ 346*fb4d8502Sjsg void amdgpu_i2c_fini(struct amdgpu_device *adev) 347*fb4d8502Sjsg { 348*fb4d8502Sjsg int i; 349*fb4d8502Sjsg 350*fb4d8502Sjsg for (i = 0; i < AMDGPU_MAX_I2C_BUS; i++) { 351*fb4d8502Sjsg if (adev->i2c_bus[i]) { 352*fb4d8502Sjsg amdgpu_i2c_destroy(adev->i2c_bus[i]); 353*fb4d8502Sjsg adev->i2c_bus[i] = NULL; 354*fb4d8502Sjsg } 355*fb4d8502Sjsg } 356*fb4d8502Sjsg } 357*fb4d8502Sjsg 358*fb4d8502Sjsg /* Add additional buses */ 359*fb4d8502Sjsg void amdgpu_i2c_add(struct amdgpu_device *adev, 360*fb4d8502Sjsg const struct amdgpu_i2c_bus_rec *rec, 361*fb4d8502Sjsg const char *name) 362*fb4d8502Sjsg { 363*fb4d8502Sjsg struct drm_device *dev = adev->ddev; 364*fb4d8502Sjsg int i; 365*fb4d8502Sjsg 366*fb4d8502Sjsg for (i = 0; i < AMDGPU_MAX_I2C_BUS; i++) { 367*fb4d8502Sjsg if (!adev->i2c_bus[i]) { 368*fb4d8502Sjsg adev->i2c_bus[i] = amdgpu_i2c_create(dev, rec, name); 369*fb4d8502Sjsg return; 370*fb4d8502Sjsg } 371*fb4d8502Sjsg } 372*fb4d8502Sjsg } 373*fb4d8502Sjsg 374*fb4d8502Sjsg /* looks up bus based on id */ 375*fb4d8502Sjsg struct amdgpu_i2c_chan * 376*fb4d8502Sjsg amdgpu_i2c_lookup(struct amdgpu_device *adev, 377*fb4d8502Sjsg const struct amdgpu_i2c_bus_rec *i2c_bus) 378*fb4d8502Sjsg { 379*fb4d8502Sjsg int i; 380*fb4d8502Sjsg 381*fb4d8502Sjsg for (i = 0; i < AMDGPU_MAX_I2C_BUS; i++) { 382*fb4d8502Sjsg if (adev->i2c_bus[i] && 383*fb4d8502Sjsg (adev->i2c_bus[i]->rec.i2c_id == i2c_bus->i2c_id)) { 384*fb4d8502Sjsg return adev->i2c_bus[i]; 385*fb4d8502Sjsg } 386*fb4d8502Sjsg } 387*fb4d8502Sjsg return NULL; 388*fb4d8502Sjsg } 389*fb4d8502Sjsg 390*fb4d8502Sjsg static void amdgpu_i2c_get_byte(struct amdgpu_i2c_chan *i2c_bus, 391*fb4d8502Sjsg u8 slave_addr, 392*fb4d8502Sjsg u8 addr, 393*fb4d8502Sjsg u8 *val) 394*fb4d8502Sjsg { 395*fb4d8502Sjsg u8 out_buf[2]; 396*fb4d8502Sjsg u8 in_buf[2]; 397*fb4d8502Sjsg struct i2c_msg msgs[] = { 398*fb4d8502Sjsg { 399*fb4d8502Sjsg .addr = slave_addr, 400*fb4d8502Sjsg .flags = 0, 401*fb4d8502Sjsg .len = 1, 402*fb4d8502Sjsg .buf = out_buf, 403*fb4d8502Sjsg }, 404*fb4d8502Sjsg { 405*fb4d8502Sjsg .addr = slave_addr, 406*fb4d8502Sjsg .flags = I2C_M_RD, 407*fb4d8502Sjsg .len = 1, 408*fb4d8502Sjsg .buf = in_buf, 409*fb4d8502Sjsg } 410*fb4d8502Sjsg }; 411*fb4d8502Sjsg 412*fb4d8502Sjsg out_buf[0] = addr; 413*fb4d8502Sjsg out_buf[1] = 0; 414*fb4d8502Sjsg 415*fb4d8502Sjsg if (i2c_transfer(&i2c_bus->adapter, msgs, 2) == 2) { 416*fb4d8502Sjsg *val = in_buf[0]; 417*fb4d8502Sjsg DRM_DEBUG("val = 0x%02x\n", *val); 418*fb4d8502Sjsg } else { 419*fb4d8502Sjsg DRM_DEBUG("i2c 0x%02x 0x%02x read failed\n", 420*fb4d8502Sjsg addr, *val); 421*fb4d8502Sjsg } 422*fb4d8502Sjsg } 423*fb4d8502Sjsg 424*fb4d8502Sjsg static void amdgpu_i2c_put_byte(struct amdgpu_i2c_chan *i2c_bus, 425*fb4d8502Sjsg u8 slave_addr, 426*fb4d8502Sjsg u8 addr, 427*fb4d8502Sjsg u8 val) 428*fb4d8502Sjsg { 429*fb4d8502Sjsg uint8_t out_buf[2]; 430*fb4d8502Sjsg struct i2c_msg msg = { 431*fb4d8502Sjsg .addr = slave_addr, 432*fb4d8502Sjsg .flags = 0, 433*fb4d8502Sjsg .len = 2, 434*fb4d8502Sjsg .buf = out_buf, 435*fb4d8502Sjsg }; 436*fb4d8502Sjsg 437*fb4d8502Sjsg out_buf[0] = addr; 438*fb4d8502Sjsg out_buf[1] = val; 439*fb4d8502Sjsg 440*fb4d8502Sjsg if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1) 441*fb4d8502Sjsg DRM_DEBUG("i2c 0x%02x 0x%02x write failed\n", 442*fb4d8502Sjsg addr, val); 443*fb4d8502Sjsg } 444*fb4d8502Sjsg 445*fb4d8502Sjsg /* ddc router switching */ 446*fb4d8502Sjsg void 447*fb4d8502Sjsg amdgpu_i2c_router_select_ddc_port(const struct amdgpu_connector *amdgpu_connector) 448*fb4d8502Sjsg { 449*fb4d8502Sjsg u8 val; 450*fb4d8502Sjsg 451*fb4d8502Sjsg if (!amdgpu_connector->router.ddc_valid) 452*fb4d8502Sjsg return; 453*fb4d8502Sjsg 454*fb4d8502Sjsg if (!amdgpu_connector->router_bus) 455*fb4d8502Sjsg return; 456*fb4d8502Sjsg 457*fb4d8502Sjsg amdgpu_i2c_get_byte(amdgpu_connector->router_bus, 458*fb4d8502Sjsg amdgpu_connector->router.i2c_addr, 459*fb4d8502Sjsg 0x3, &val); 460*fb4d8502Sjsg val &= ~amdgpu_connector->router.ddc_mux_control_pin; 461*fb4d8502Sjsg amdgpu_i2c_put_byte(amdgpu_connector->router_bus, 462*fb4d8502Sjsg amdgpu_connector->router.i2c_addr, 463*fb4d8502Sjsg 0x3, val); 464*fb4d8502Sjsg amdgpu_i2c_get_byte(amdgpu_connector->router_bus, 465*fb4d8502Sjsg amdgpu_connector->router.i2c_addr, 466*fb4d8502Sjsg 0x1, &val); 467*fb4d8502Sjsg val &= ~amdgpu_connector->router.ddc_mux_control_pin; 468*fb4d8502Sjsg val |= amdgpu_connector->router.ddc_mux_state; 469*fb4d8502Sjsg amdgpu_i2c_put_byte(amdgpu_connector->router_bus, 470*fb4d8502Sjsg amdgpu_connector->router.i2c_addr, 471*fb4d8502Sjsg 0x1, val); 472*fb4d8502Sjsg } 473*fb4d8502Sjsg 474*fb4d8502Sjsg /* clock/data router switching */ 475*fb4d8502Sjsg void 476*fb4d8502Sjsg amdgpu_i2c_router_select_cd_port(const struct amdgpu_connector *amdgpu_connector) 477*fb4d8502Sjsg { 478*fb4d8502Sjsg u8 val; 479*fb4d8502Sjsg 480*fb4d8502Sjsg if (!amdgpu_connector->router.cd_valid) 481*fb4d8502Sjsg return; 482*fb4d8502Sjsg 483*fb4d8502Sjsg if (!amdgpu_connector->router_bus) 484*fb4d8502Sjsg return; 485*fb4d8502Sjsg 486*fb4d8502Sjsg amdgpu_i2c_get_byte(amdgpu_connector->router_bus, 487*fb4d8502Sjsg amdgpu_connector->router.i2c_addr, 488*fb4d8502Sjsg 0x3, &val); 489*fb4d8502Sjsg val &= ~amdgpu_connector->router.cd_mux_control_pin; 490*fb4d8502Sjsg amdgpu_i2c_put_byte(amdgpu_connector->router_bus, 491*fb4d8502Sjsg amdgpu_connector->router.i2c_addr, 492*fb4d8502Sjsg 0x3, val); 493*fb4d8502Sjsg amdgpu_i2c_get_byte(amdgpu_connector->router_bus, 494*fb4d8502Sjsg amdgpu_connector->router.i2c_addr, 495*fb4d8502Sjsg 0x1, &val); 496*fb4d8502Sjsg val &= ~amdgpu_connector->router.cd_mux_control_pin; 497*fb4d8502Sjsg val |= amdgpu_connector->router.cd_mux_state; 498*fb4d8502Sjsg amdgpu_i2c_put_byte(amdgpu_connector->router_bus, 499*fb4d8502Sjsg amdgpu_connector->router.i2c_addr, 500*fb4d8502Sjsg 0x1, val); 501*fb4d8502Sjsg } 502