Path: blob/master/drivers/gpu/drm/i915/dvo_sil164.c
15113 views
/**************************************************************************12Copyright © 2006 Dave Airlie34All Rights Reserved.56Permission is hereby granted, free of charge, to any person obtaining a7copy of this software and associated documentation files (the8"Software"), to deal in the Software without restriction, including9without limitation the rights to use, copy, modify, merge, publish,10distribute, sub license, and/or sell copies of the Software, and to11permit persons to whom the Software is furnished to do so, subject to12the following conditions:1314The above copyright notice and this permission notice (including the15next paragraph) shall be included in all copies or substantial portions16of the Software.1718THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS19OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.21IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR22ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,23TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE24SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.2526**************************************************************************/2728#include "dvo.h"2930#define SIL164_VID 0x000131#define SIL164_DID 0x00063233#define SIL164_VID_LO 0x0034#define SIL164_VID_HI 0x0135#define SIL164_DID_LO 0x0236#define SIL164_DID_HI 0x0337#define SIL164_REV 0x0438#define SIL164_RSVD 0x0539#define SIL164_FREQ_LO 0x0640#define SIL164_FREQ_HI 0x074142#define SIL164_REG8 0x0843#define SIL164_8_VEN (1<<5)44#define SIL164_8_HEN (1<<4)45#define SIL164_8_DSEL (1<<3)46#define SIL164_8_BSEL (1<<2)47#define SIL164_8_EDGE (1<<1)48#define SIL164_8_PD (1<<0)4950#define SIL164_REG9 0x0951#define SIL164_9_VLOW (1<<7)52#define SIL164_9_MSEL_MASK (0x7<<4)53#define SIL164_9_TSEL (1<<3)54#define SIL164_9_RSEN (1<<2)55#define SIL164_9_HTPLG (1<<1)56#define SIL164_9_MDI (1<<0)5758#define SIL164_REGC 0x0c5960struct sil164_priv {61//I2CDevRec d;62bool quiet;63};6465#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))6667static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)68{69struct sil164_priv *sil = dvo->dev_priv;70struct i2c_adapter *adapter = dvo->i2c_bus;71u8 out_buf[2];72u8 in_buf[2];7374struct i2c_msg msgs[] = {75{76.addr = dvo->slave_addr,77.flags = 0,78.len = 1,79.buf = out_buf,80},81{82.addr = dvo->slave_addr,83.flags = I2C_M_RD,84.len = 1,85.buf = in_buf,86}87};8889out_buf[0] = addr;90out_buf[1] = 0;9192if (i2c_transfer(adapter, msgs, 2) == 2) {93*ch = in_buf[0];94return true;95};9697if (!sil->quiet) {98DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",99addr, adapter->name, dvo->slave_addr);100}101return false;102}103104static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)105{106struct sil164_priv *sil= dvo->dev_priv;107struct i2c_adapter *adapter = dvo->i2c_bus;108uint8_t out_buf[2];109struct i2c_msg msg = {110.addr = dvo->slave_addr,111.flags = 0,112.len = 2,113.buf = out_buf,114};115116out_buf[0] = addr;117out_buf[1] = ch;118119if (i2c_transfer(adapter, &msg, 1) == 1)120return true;121122if (!sil->quiet) {123DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",124addr, adapter->name, dvo->slave_addr);125}126127return false;128}129130/* Silicon Image 164 driver for chip on i2c bus */131static bool sil164_init(struct intel_dvo_device *dvo,132struct i2c_adapter *adapter)133{134/* this will detect the SIL164 chip on the specified i2c bus */135struct sil164_priv *sil;136unsigned char ch;137138sil = kzalloc(sizeof(struct sil164_priv), GFP_KERNEL);139if (sil == NULL)140return false;141142dvo->i2c_bus = adapter;143dvo->dev_priv = sil;144sil->quiet = true;145146if (!sil164_readb(dvo, SIL164_VID_LO, &ch))147goto out;148149if (ch != (SIL164_VID & 0xff)) {150DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",151ch, adapter->name, dvo->slave_addr);152goto out;153}154155if (!sil164_readb(dvo, SIL164_DID_LO, &ch))156goto out;157158if (ch != (SIL164_DID & 0xff)) {159DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",160ch, adapter->name, dvo->slave_addr);161goto out;162}163sil->quiet = false;164165DRM_DEBUG_KMS("init sil164 dvo controller successfully!\n");166return true;167168out:169kfree(sil);170return false;171}172173static enum drm_connector_status sil164_detect(struct intel_dvo_device *dvo)174{175uint8_t reg9;176177sil164_readb(dvo, SIL164_REG9, ®9);178179if (reg9 & SIL164_9_HTPLG)180return connector_status_connected;181else182return connector_status_disconnected;183}184185static enum drm_mode_status sil164_mode_valid(struct intel_dvo_device *dvo,186struct drm_display_mode *mode)187{188return MODE_OK;189}190191static void sil164_mode_set(struct intel_dvo_device *dvo,192struct drm_display_mode *mode,193struct drm_display_mode *adjusted_mode)194{195/* As long as the basics are set up, since we don't have clock196* dependencies in the mode setup, we can just leave the197* registers alone and everything will work fine.198*/199/* recommended programming sequence from doc */200/*sil164_writeb(sil, 0x08, 0x30);201sil164_writeb(sil, 0x09, 0x00);202sil164_writeb(sil, 0x0a, 0x90);203sil164_writeb(sil, 0x0c, 0x89);204sil164_writeb(sil, 0x08, 0x31);*/205/* don't do much */206return;207}208209/* set the SIL164 power state */210static void sil164_dpms(struct intel_dvo_device *dvo, int mode)211{212int ret;213unsigned char ch;214215ret = sil164_readb(dvo, SIL164_REG8, &ch);216if (ret == false)217return;218219if (mode == DRM_MODE_DPMS_ON)220ch |= SIL164_8_PD;221else222ch &= ~SIL164_8_PD;223224sil164_writeb(dvo, SIL164_REG8, ch);225return;226}227228static void sil164_dump_regs(struct intel_dvo_device *dvo)229{230uint8_t val;231232sil164_readb(dvo, SIL164_FREQ_LO, &val);233DRM_LOG_KMS("SIL164_FREQ_LO: 0x%02x\n", val);234sil164_readb(dvo, SIL164_FREQ_HI, &val);235DRM_LOG_KMS("SIL164_FREQ_HI: 0x%02x\n", val);236sil164_readb(dvo, SIL164_REG8, &val);237DRM_LOG_KMS("SIL164_REG8: 0x%02x\n", val);238sil164_readb(dvo, SIL164_REG9, &val);239DRM_LOG_KMS("SIL164_REG9: 0x%02x\n", val);240sil164_readb(dvo, SIL164_REGC, &val);241DRM_LOG_KMS("SIL164_REGC: 0x%02x\n", val);242}243244static void sil164_destroy(struct intel_dvo_device *dvo)245{246struct sil164_priv *sil = dvo->dev_priv;247248if (sil) {249kfree(sil);250dvo->dev_priv = NULL;251}252}253254struct intel_dvo_dev_ops sil164_ops = {255.init = sil164_init,256.detect = sil164_detect,257.mode_valid = sil164_mode_valid,258.mode_set = sil164_mode_set,259.dpms = sil164_dpms,260.dump_regs = sil164_dump_regs,261.destroy = sil164_destroy,262};263264265