Home | History | Annotate | Line # | Download | only in display
      1  1.1  riastrad /*	$NetBSD: dvo_ch7017.c,v 1.2 2021/12/18 23:45:29 riastradh Exp $	*/
      2  1.1  riastrad 
      3  1.1  riastrad /*
      4  1.1  riastrad  * Copyright  2006 Intel Corporation
      5  1.1  riastrad  *
      6  1.1  riastrad  * Permission is hereby granted, free of charge, to any person obtaining a
      7  1.1  riastrad  * copy of this software and associated documentation files (the "Software"),
      8  1.1  riastrad  * to deal in the Software without restriction, including without limitation
      9  1.1  riastrad  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  1.1  riastrad  * and/or sell copies of the Software, and to permit persons to whom the
     11  1.1  riastrad  * Software is furnished to do so, subject to the following conditions:
     12  1.1  riastrad  *
     13  1.1  riastrad  * The above copyright notice and this permission notice (including the next
     14  1.1  riastrad  * paragraph) shall be included in all copies or substantial portions of the
     15  1.1  riastrad  * Software.
     16  1.1  riastrad  *
     17  1.1  riastrad  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  1.1  riastrad  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  1.1  riastrad  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  1.1  riastrad  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  1.1  riastrad  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  1.1  riastrad  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23  1.1  riastrad  * DEALINGS IN THE SOFTWARE.
     24  1.1  riastrad  *
     25  1.1  riastrad  * Authors:
     26  1.1  riastrad  *    Eric Anholt <eric (at) anholt.net>
     27  1.1  riastrad  *
     28  1.1  riastrad  */
     29  1.1  riastrad 
     30  1.1  riastrad #include <sys/cdefs.h>
     31  1.1  riastrad __KERNEL_RCSID(0, "$NetBSD: dvo_ch7017.c,v 1.2 2021/12/18 23:45:29 riastradh Exp $");
     32  1.1  riastrad 
     33  1.1  riastrad #include "intel_display_types.h"
     34  1.1  riastrad #include "intel_dvo_dev.h"
     35  1.1  riastrad 
     36  1.1  riastrad #define CH7017_TV_DISPLAY_MODE		0x00
     37  1.1  riastrad #define CH7017_FLICKER_FILTER		0x01
     38  1.1  riastrad #define CH7017_VIDEO_BANDWIDTH		0x02
     39  1.1  riastrad #define CH7017_TEXT_ENHANCEMENT		0x03
     40  1.1  riastrad #define CH7017_START_ACTIVE_VIDEO	0x04
     41  1.1  riastrad #define CH7017_HORIZONTAL_POSITION	0x05
     42  1.1  riastrad #define CH7017_VERTICAL_POSITION	0x06
     43  1.1  riastrad #define CH7017_BLACK_LEVEL		0x07
     44  1.1  riastrad #define CH7017_CONTRAST_ENHANCEMENT	0x08
     45  1.1  riastrad #define CH7017_TV_PLL			0x09
     46  1.1  riastrad #define CH7017_TV_PLL_M			0x0a
     47  1.1  riastrad #define CH7017_TV_PLL_N			0x0b
     48  1.1  riastrad #define CH7017_SUB_CARRIER_0		0x0c
     49  1.1  riastrad #define CH7017_CIV_CONTROL		0x10
     50  1.1  riastrad #define CH7017_CIV_0			0x11
     51  1.1  riastrad #define CH7017_CHROMA_BOOST		0x14
     52  1.1  riastrad #define CH7017_CLOCK_MODE		0x1c
     53  1.1  riastrad #define CH7017_INPUT_CLOCK		0x1d
     54  1.1  riastrad #define CH7017_GPIO_CONTROL		0x1e
     55  1.1  riastrad #define CH7017_INPUT_DATA_FORMAT	0x1f
     56  1.1  riastrad #define CH7017_CONNECTION_DETECT	0x20
     57  1.1  riastrad #define CH7017_DAC_CONTROL		0x21
     58  1.1  riastrad #define CH7017_BUFFERED_CLOCK_OUTPUT	0x22
     59  1.1  riastrad #define CH7017_DEFEAT_VSYNC		0x47
     60  1.1  riastrad #define CH7017_TEST_PATTERN		0x48
     61  1.1  riastrad 
     62  1.1  riastrad #define CH7017_POWER_MANAGEMENT		0x49
     63  1.1  riastrad /** Enables the TV output path. */
     64  1.1  riastrad #define CH7017_TV_EN			(1 << 0)
     65  1.1  riastrad #define CH7017_DAC0_POWER_DOWN		(1 << 1)
     66  1.1  riastrad #define CH7017_DAC1_POWER_DOWN		(1 << 2)
     67  1.1  riastrad #define CH7017_DAC2_POWER_DOWN		(1 << 3)
     68  1.1  riastrad #define CH7017_DAC3_POWER_DOWN		(1 << 4)
     69  1.1  riastrad /** Powers down the TV out block, and DAC0-3 */
     70  1.1  riastrad #define CH7017_TV_POWER_DOWN_EN		(1 << 5)
     71  1.1  riastrad 
     72  1.1  riastrad #define CH7017_VERSION_ID		0x4a
     73  1.1  riastrad 
     74  1.1  riastrad #define CH7017_DEVICE_ID		0x4b
     75  1.1  riastrad #define CH7017_DEVICE_ID_VALUE		0x1b
     76  1.1  riastrad #define CH7018_DEVICE_ID_VALUE		0x1a
     77  1.1  riastrad #define CH7019_DEVICE_ID_VALUE		0x19
     78  1.1  riastrad 
     79  1.1  riastrad #define CH7017_XCLK_D2_ADJUST		0x53
     80  1.1  riastrad #define CH7017_UP_SCALER_COEFF_0	0x55
     81  1.1  riastrad #define CH7017_UP_SCALER_COEFF_1	0x56
     82  1.1  riastrad #define CH7017_UP_SCALER_COEFF_2	0x57
     83  1.1  riastrad #define CH7017_UP_SCALER_COEFF_3	0x58
     84  1.1  riastrad #define CH7017_UP_SCALER_COEFF_4	0x59
     85  1.1  riastrad #define CH7017_UP_SCALER_VERTICAL_INC_0	0x5a
     86  1.1  riastrad #define CH7017_UP_SCALER_VERTICAL_INC_1	0x5b
     87  1.1  riastrad #define CH7017_GPIO_INVERT		0x5c
     88  1.1  riastrad #define CH7017_UP_SCALER_HORIZONTAL_INC_0	0x5d
     89  1.1  riastrad #define CH7017_UP_SCALER_HORIZONTAL_INC_1	0x5e
     90  1.1  riastrad 
     91  1.1  riastrad #define CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT	0x5f
     92  1.1  riastrad /**< Low bits of horizontal active pixel input */
     93  1.1  riastrad 
     94  1.1  riastrad #define CH7017_ACTIVE_INPUT_LINE_OUTPUT	0x60
     95  1.1  riastrad /** High bits of horizontal active pixel input */
     96  1.1  riastrad #define CH7017_LVDS_HAP_INPUT_MASK	(0x7 << 0)
     97  1.1  riastrad /** High bits of vertical active line output */
     98  1.1  riastrad #define CH7017_LVDS_VAL_HIGH_MASK	(0x7 << 3)
     99  1.1  riastrad 
    100  1.1  riastrad #define CH7017_VERTICAL_ACTIVE_LINE_OUTPUT	0x61
    101  1.1  riastrad /**< Low bits of vertical active line output */
    102  1.1  riastrad 
    103  1.1  riastrad #define CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT	0x62
    104  1.1  riastrad /**< Low bits of horizontal active pixel output */
    105  1.1  riastrad 
    106  1.1  riastrad #define CH7017_LVDS_POWER_DOWN		0x63
    107  1.1  riastrad /** High bits of horizontal active pixel output */
    108  1.1  riastrad #define CH7017_LVDS_HAP_HIGH_MASK	(0x7 << 0)
    109  1.1  riastrad /** Enables the LVDS power down state transition */
    110  1.1  riastrad #define CH7017_LVDS_POWER_DOWN_EN	(1 << 6)
    111  1.1  riastrad /** Enables the LVDS upscaler */
    112  1.1  riastrad #define CH7017_LVDS_UPSCALER_EN		(1 << 7)
    113  1.1  riastrad #define CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED 0x08
    114  1.1  riastrad 
    115  1.1  riastrad #define CH7017_LVDS_ENCODING		0x64
    116  1.1  riastrad #define CH7017_LVDS_DITHER_2D		(1 << 2)
    117  1.1  riastrad #define CH7017_LVDS_DITHER_DIS		(1 << 3)
    118  1.1  riastrad #define CH7017_LVDS_DUAL_CHANNEL_EN	(1 << 4)
    119  1.1  riastrad #define CH7017_LVDS_24_BIT		(1 << 5)
    120  1.1  riastrad 
    121  1.1  riastrad #define CH7017_LVDS_ENCODING_2		0x65
    122  1.1  riastrad 
    123  1.1  riastrad #define CH7017_LVDS_PLL_CONTROL		0x66
    124  1.1  riastrad /** Enables the LVDS panel output path */
    125  1.1  riastrad #define CH7017_LVDS_PANEN		(1 << 0)
    126  1.1  riastrad /** Enables the LVDS panel backlight */
    127  1.1  riastrad #define CH7017_LVDS_BKLEN		(1 << 3)
    128  1.1  riastrad 
    129  1.1  riastrad #define CH7017_POWER_SEQUENCING_T1	0x67
    130  1.1  riastrad #define CH7017_POWER_SEQUENCING_T2	0x68
    131  1.1  riastrad #define CH7017_POWER_SEQUENCING_T3	0x69
    132  1.1  riastrad #define CH7017_POWER_SEQUENCING_T4	0x6a
    133  1.1  riastrad #define CH7017_POWER_SEQUENCING_T5	0x6b
    134  1.1  riastrad #define CH7017_GPIO_DRIVER_TYPE		0x6c
    135  1.1  riastrad #define CH7017_GPIO_DATA		0x6d
    136  1.1  riastrad #define CH7017_GPIO_DIRECTION_CONTROL	0x6e
    137  1.1  riastrad 
    138  1.1  riastrad #define CH7017_LVDS_PLL_FEEDBACK_DIV	0x71
    139  1.1  riastrad # define CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT 4
    140  1.1  riastrad # define CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT 0
    141  1.1  riastrad # define CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED 0x80
    142  1.1  riastrad 
    143  1.1  riastrad #define CH7017_LVDS_PLL_VCO_CONTROL	0x72
    144  1.1  riastrad # define CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED 0x80
    145  1.1  riastrad # define CH7017_LVDS_PLL_VCO_SHIFT	4
    146  1.1  riastrad # define CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT 0
    147  1.1  riastrad 
    148  1.1  riastrad #define CH7017_OUTPUTS_ENABLE		0x73
    149  1.1  riastrad # define CH7017_CHARGE_PUMP_LOW		0x0
    150  1.1  riastrad # define CH7017_CHARGE_PUMP_HIGH	0x3
    151  1.1  riastrad # define CH7017_LVDS_CHANNEL_A		(1 << 3)
    152  1.1  riastrad # define CH7017_LVDS_CHANNEL_B		(1 << 4)
    153  1.1  riastrad # define CH7017_TV_DAC_A		(1 << 5)
    154  1.1  riastrad # define CH7017_TV_DAC_B		(1 << 6)
    155  1.1  riastrad # define CH7017_DDC_SELECT_DC2		(1 << 7)
    156  1.1  riastrad 
    157  1.1  riastrad #define CH7017_LVDS_OUTPUT_AMPLITUDE	0x74
    158  1.1  riastrad #define CH7017_LVDS_PLL_EMI_REDUCTION	0x75
    159  1.1  riastrad #define CH7017_LVDS_POWER_DOWN_FLICKER	0x76
    160  1.1  riastrad 
    161  1.1  riastrad #define CH7017_LVDS_CONTROL_2		0x78
    162  1.1  riastrad # define CH7017_LOOP_FILTER_SHIFT	5
    163  1.1  riastrad # define CH7017_PHASE_DETECTOR_SHIFT	0
    164  1.1  riastrad 
    165  1.1  riastrad #define CH7017_BANG_LIMIT_CONTROL	0x7f
    166  1.1  riastrad 
    167  1.1  riastrad struct ch7017_priv {
    168  1.1  riastrad 	u8 dummy;
    169  1.1  riastrad };
    170  1.1  riastrad 
    171  1.1  riastrad static void ch7017_dump_regs(struct intel_dvo_device *dvo);
    172  1.1  riastrad static void ch7017_dpms(struct intel_dvo_device *dvo, bool enable);
    173  1.1  riastrad 
    174  1.1  riastrad static bool ch7017_read(struct intel_dvo_device *dvo, u8 addr, u8 *val)
    175  1.1  riastrad {
    176  1.1  riastrad 	struct i2c_msg msgs[] = {
    177  1.1  riastrad 		{
    178  1.1  riastrad 			.addr = dvo->slave_addr,
    179  1.1  riastrad 			.flags = 0,
    180  1.1  riastrad 			.len = 1,
    181  1.1  riastrad 			.buf = &addr,
    182  1.1  riastrad 		},
    183  1.1  riastrad 		{
    184  1.1  riastrad 			.addr = dvo->slave_addr,
    185  1.1  riastrad 			.flags = I2C_M_RD,
    186  1.1  riastrad 			.len = 1,
    187  1.1  riastrad 			.buf = val,
    188  1.1  riastrad 		}
    189  1.1  riastrad 	};
    190  1.1  riastrad 	return i2c_transfer(dvo->i2c_bus, msgs, 2) == 2;
    191  1.1  riastrad }
    192  1.1  riastrad 
    193  1.1  riastrad static bool ch7017_write(struct intel_dvo_device *dvo, u8 addr, u8 val)
    194  1.1  riastrad {
    195  1.1  riastrad 	u8 buf[2] = { addr, val };
    196  1.1  riastrad 	struct i2c_msg msg = {
    197  1.1  riastrad 		.addr = dvo->slave_addr,
    198  1.1  riastrad 		.flags = 0,
    199  1.1  riastrad 		.len = 2,
    200  1.1  riastrad 		.buf = buf,
    201  1.1  riastrad 	};
    202  1.1  riastrad 	return i2c_transfer(dvo->i2c_bus, &msg, 1) == 1;
    203  1.1  riastrad }
    204  1.1  riastrad 
    205  1.1  riastrad /** Probes for a CH7017 on the given bus and slave address. */
    206  1.1  riastrad static bool ch7017_init(struct intel_dvo_device *dvo,
    207  1.1  riastrad 			struct i2c_adapter *adapter)
    208  1.1  riastrad {
    209  1.1  riastrad 	struct ch7017_priv *priv;
    210  1.1  riastrad 	const char *str;
    211  1.1  riastrad 	u8 val;
    212  1.1  riastrad 
    213  1.1  riastrad 	priv = kzalloc(sizeof(struct ch7017_priv), GFP_KERNEL);
    214  1.1  riastrad 	if (priv == NULL)
    215  1.1  riastrad 		return false;
    216  1.1  riastrad 
    217  1.1  riastrad 	dvo->i2c_bus = adapter;
    218  1.1  riastrad 	dvo->dev_priv = priv;
    219  1.1  riastrad 
    220  1.1  riastrad 	if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val))
    221  1.1  riastrad 		goto fail;
    222  1.1  riastrad 
    223  1.1  riastrad 	switch (val) {
    224  1.1  riastrad 	case CH7017_DEVICE_ID_VALUE:
    225  1.1  riastrad 		str = "ch7017";
    226  1.1  riastrad 		break;
    227  1.1  riastrad 	case CH7018_DEVICE_ID_VALUE:
    228  1.1  riastrad 		str = "ch7018";
    229  1.1  riastrad 		break;
    230  1.1  riastrad 	case CH7019_DEVICE_ID_VALUE:
    231  1.1  riastrad 		str = "ch7019";
    232  1.1  riastrad 		break;
    233  1.1  riastrad 	default:
    234  1.1  riastrad 		DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
    235  1.1  riastrad 			      "slave %d.\n",
    236  1.1  riastrad 			      val, adapter->name, dvo->slave_addr);
    237  1.1  riastrad 		goto fail;
    238  1.1  riastrad 	}
    239  1.1  riastrad 
    240  1.1  riastrad 	DRM_DEBUG_KMS("%s detected on %s, addr %d\n",
    241  1.1  riastrad 		      str, adapter->name, dvo->slave_addr);
    242  1.1  riastrad 	return true;
    243  1.1  riastrad 
    244  1.1  riastrad fail:
    245  1.1  riastrad 	kfree(priv);
    246  1.1  riastrad 	return false;
    247  1.1  riastrad }
    248  1.1  riastrad 
    249  1.1  riastrad static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo)
    250  1.1  riastrad {
    251  1.1  riastrad 	return connector_status_connected;
    252  1.1  riastrad }
    253  1.1  riastrad 
    254  1.1  riastrad static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo,
    255  1.1  riastrad 					      struct drm_display_mode *mode)
    256  1.1  riastrad {
    257  1.1  riastrad 	if (mode->clock > 160000)
    258  1.1  riastrad 		return MODE_CLOCK_HIGH;
    259  1.1  riastrad 
    260  1.1  riastrad 	return MODE_OK;
    261  1.1  riastrad }
    262  1.1  riastrad 
    263  1.1  riastrad static void ch7017_mode_set(struct intel_dvo_device *dvo,
    264  1.1  riastrad 			    const struct drm_display_mode *mode,
    265  1.1  riastrad 			    const struct drm_display_mode *adjusted_mode)
    266  1.1  riastrad {
    267  1.1  riastrad 	u8 lvds_pll_feedback_div, lvds_pll_vco_control;
    268  1.1  riastrad 	u8 outputs_enable, lvds_control_2, lvds_power_down;
    269  1.1  riastrad 	u8 horizontal_active_pixel_input;
    270  1.1  riastrad 	u8 horizontal_active_pixel_output, vertical_active_line_output;
    271  1.1  riastrad 	u8 active_input_line_output;
    272  1.1  riastrad 
    273  1.1  riastrad 	DRM_DEBUG_KMS("Registers before mode setting\n");
    274  1.1  riastrad 	ch7017_dump_regs(dvo);
    275  1.1  riastrad 
    276  1.1  riastrad 	/* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/
    277  1.1  riastrad 	if (mode->clock < 100000) {
    278  1.1  riastrad 		outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_LOW;
    279  1.1  riastrad 		lvds_pll_feedback_div = CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED |
    280  1.1  riastrad 			(2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) |
    281  1.1  riastrad 			(13 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT);
    282  1.1  riastrad 		lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
    283  1.1  riastrad 			(2 << CH7017_LVDS_PLL_VCO_SHIFT) |
    284  1.1  riastrad 			(3 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
    285  1.1  riastrad 		lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) |
    286  1.1  riastrad 			(0 << CH7017_PHASE_DETECTOR_SHIFT);
    287  1.1  riastrad 	} else {
    288  1.1  riastrad 		outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_HIGH;
    289  1.1  riastrad 		lvds_pll_feedback_div =
    290  1.1  riastrad 			CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED |
    291  1.1  riastrad 			(2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) |
    292  1.1  riastrad 			(3 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT);
    293  1.1  riastrad 		lvds_control_2 = (3 << CH7017_LOOP_FILTER_SHIFT) |
    294  1.1  riastrad 			(0 << CH7017_PHASE_DETECTOR_SHIFT);
    295  1.1  riastrad 		if (1) { /* XXX: dual channel panel detection.  Assume yes for now. */
    296  1.1  riastrad 			outputs_enable |= CH7017_LVDS_CHANNEL_B;
    297  1.1  riastrad 			lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
    298  1.1  riastrad 				(2 << CH7017_LVDS_PLL_VCO_SHIFT) |
    299  1.1  riastrad 				(13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
    300  1.1  riastrad 		} else {
    301  1.1  riastrad 			lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
    302  1.1  riastrad 				(1 << CH7017_LVDS_PLL_VCO_SHIFT) |
    303  1.1  riastrad 				(13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
    304  1.1  riastrad 		}
    305  1.1  riastrad 	}
    306  1.1  riastrad 
    307  1.1  riastrad 	horizontal_active_pixel_input = mode->hdisplay & 0x00ff;
    308  1.1  riastrad 
    309  1.1  riastrad 	vertical_active_line_output = mode->vdisplay & 0x00ff;
    310  1.1  riastrad 	horizontal_active_pixel_output = mode->hdisplay & 0x00ff;
    311  1.1  riastrad 
    312  1.1  riastrad 	active_input_line_output = ((mode->hdisplay & 0x0700) >> 8) |
    313  1.1  riastrad 				   (((mode->vdisplay & 0x0700) >> 8) << 3);
    314  1.1  riastrad 
    315  1.1  riastrad 	lvds_power_down = CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED |
    316  1.1  riastrad 			  (mode->hdisplay & 0x0700) >> 8;
    317  1.1  riastrad 
    318  1.1  riastrad 	ch7017_dpms(dvo, false);
    319  1.1  riastrad 	ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT,
    320  1.1  riastrad 			horizontal_active_pixel_input);
    321  1.1  riastrad 	ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT,
    322  1.1  riastrad 			horizontal_active_pixel_output);
    323  1.1  riastrad 	ch7017_write(dvo, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT,
    324  1.1  riastrad 			vertical_active_line_output);
    325  1.1  riastrad 	ch7017_write(dvo, CH7017_ACTIVE_INPUT_LINE_OUTPUT,
    326  1.1  riastrad 			active_input_line_output);
    327  1.1  riastrad 	ch7017_write(dvo, CH7017_LVDS_PLL_VCO_CONTROL, lvds_pll_vco_control);
    328  1.1  riastrad 	ch7017_write(dvo, CH7017_LVDS_PLL_FEEDBACK_DIV, lvds_pll_feedback_div);
    329  1.1  riastrad 	ch7017_write(dvo, CH7017_LVDS_CONTROL_2, lvds_control_2);
    330  1.1  riastrad 	ch7017_write(dvo, CH7017_OUTPUTS_ENABLE, outputs_enable);
    331  1.1  riastrad 
    332  1.1  riastrad 	/* Turn the LVDS back on with new settings. */
    333  1.1  riastrad 	ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, lvds_power_down);
    334  1.1  riastrad 
    335  1.1  riastrad 	DRM_DEBUG_KMS("Registers after mode setting\n");
    336  1.1  riastrad 	ch7017_dump_regs(dvo);
    337  1.1  riastrad }
    338  1.1  riastrad 
    339  1.1  riastrad /* set the CH7017 power state */
    340  1.1  riastrad static void ch7017_dpms(struct intel_dvo_device *dvo, bool enable)
    341  1.1  riastrad {
    342  1.1  riastrad 	u8 val;
    343  1.1  riastrad 
    344  1.1  riastrad 	ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &val);
    345  1.1  riastrad 
    346  1.1  riastrad 	/* Turn off TV/VGA, and never turn it on since we don't support it. */
    347  1.1  riastrad 	ch7017_write(dvo, CH7017_POWER_MANAGEMENT,
    348  1.1  riastrad 			CH7017_DAC0_POWER_DOWN |
    349  1.1  riastrad 			CH7017_DAC1_POWER_DOWN |
    350  1.1  riastrad 			CH7017_DAC2_POWER_DOWN |
    351  1.1  riastrad 			CH7017_DAC3_POWER_DOWN |
    352  1.1  riastrad 			CH7017_TV_POWER_DOWN_EN);
    353  1.1  riastrad 
    354  1.1  riastrad 	if (enable) {
    355  1.1  riastrad 		/* Turn on the LVDS */
    356  1.1  riastrad 		ch7017_write(dvo, CH7017_LVDS_POWER_DOWN,
    357  1.1  riastrad 			     val & ~CH7017_LVDS_POWER_DOWN_EN);
    358  1.1  riastrad 	} else {
    359  1.1  riastrad 		/* Turn off the LVDS */
    360  1.1  riastrad 		ch7017_write(dvo, CH7017_LVDS_POWER_DOWN,
    361  1.1  riastrad 			     val | CH7017_LVDS_POWER_DOWN_EN);
    362  1.1  riastrad 	}
    363  1.1  riastrad 
    364  1.1  riastrad 	/* XXX: Should actually wait for update power status somehow */
    365  1.1  riastrad 	msleep(20);
    366  1.1  riastrad }
    367  1.1  riastrad 
    368  1.1  riastrad static bool ch7017_get_hw_state(struct intel_dvo_device *dvo)
    369  1.1  riastrad {
    370  1.1  riastrad 	u8 val;
    371  1.1  riastrad 
    372  1.1  riastrad 	ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &val);
    373  1.1  riastrad 
    374  1.1  riastrad 	if (val & CH7017_LVDS_POWER_DOWN_EN)
    375  1.1  riastrad 		return false;
    376  1.1  riastrad 	else
    377  1.1  riastrad 		return true;
    378  1.1  riastrad }
    379  1.1  riastrad 
    380  1.1  riastrad static void ch7017_dump_regs(struct intel_dvo_device *dvo)
    381  1.1  riastrad {
    382  1.1  riastrad 	u8 val;
    383  1.1  riastrad 
    384  1.1  riastrad #define DUMP(reg)					\
    385  1.1  riastrad do {							\
    386  1.1  riastrad 	ch7017_read(dvo, reg, &val);			\
    387  1.1  riastrad 	DRM_DEBUG_KMS(#reg ": %02x\n", val);		\
    388  1.1  riastrad } while (0)
    389  1.1  riastrad 
    390  1.1  riastrad 	DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT);
    391  1.1  riastrad 	DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT);
    392  1.1  riastrad 	DUMP(CH7017_VERTICAL_ACTIVE_LINE_OUTPUT);
    393  1.1  riastrad 	DUMP(CH7017_ACTIVE_INPUT_LINE_OUTPUT);
    394  1.1  riastrad 	DUMP(CH7017_LVDS_PLL_VCO_CONTROL);
    395  1.1  riastrad 	DUMP(CH7017_LVDS_PLL_FEEDBACK_DIV);
    396  1.1  riastrad 	DUMP(CH7017_LVDS_CONTROL_2);
    397  1.1  riastrad 	DUMP(CH7017_OUTPUTS_ENABLE);
    398  1.1  riastrad 	DUMP(CH7017_LVDS_POWER_DOWN);
    399  1.1  riastrad }
    400  1.1  riastrad 
    401  1.1  riastrad static void ch7017_destroy(struct intel_dvo_device *dvo)
    402  1.1  riastrad {
    403  1.1  riastrad 	struct ch7017_priv *priv = dvo->dev_priv;
    404  1.1  riastrad 
    405  1.1  riastrad 	if (priv) {
    406  1.1  riastrad 		kfree(priv);
    407  1.1  riastrad 		dvo->dev_priv = NULL;
    408  1.1  riastrad 	}
    409  1.1  riastrad }
    410  1.1  riastrad 
    411  1.1  riastrad const struct intel_dvo_dev_ops ch7017_ops = {
    412  1.1  riastrad 	.init = ch7017_init,
    413  1.1  riastrad 	.detect = ch7017_detect,
    414  1.1  riastrad 	.mode_valid = ch7017_mode_valid,
    415  1.1  riastrad 	.mode_set = ch7017_mode_set,
    416  1.1  riastrad 	.dpms = ch7017_dpms,
    417  1.1  riastrad 	.get_hw_state = ch7017_get_hw_state,
    418  1.1  riastrad 	.dump_regs = ch7017_dump_regs,
    419  1.1  riastrad 	.destroy = ch7017_destroy,
    420  1.1  riastrad };
    421