Home | History | Annotate | Line # | Download | only in display
      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, &reg9);
    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