Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/gpu/drm/i915/display/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 12 kB image not shown  

Quelle  dvo_ch7017.c   Sprache: C

 
/*
 * Copyright © 2006 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 *    Eric Anholt <eric@anholt.net>
 *
 */


#include <drm/drm_print.h>

#include "intel_display_types.h"
#include "intel_dvo_dev.h"

#define CH7017_TV_DISPLAY_MODE  0x00
#define CH7017_FLICKER_FILTER  0x01
#define CH7017_VIDEO_BANDWIDTH  0x02
#define CH7017_TEXT_ENHANCEMENT  0x03
#define CH7017_START_ACTIVE_VIDEO 0x04
#define CH7017_HORIZONTAL_POSITION 0x05
#define CH7017_VERTICAL_POSITION 0x06
#define CH7017_BLACK_LEVEL  0x07
#define CH7017_CONTRAST_ENHANCEMENT 0x08
#define CH7017_TV_PLL   0x09
#define CH7017_TV_PLL_M   0x0a
#define CH7017_TV_PLL_N   0x0b
#define CH7017_SUB_CARRIER_0  0x0c
#define CH7017_CIV_CONTROL  0x10
#define CH7017_CIV_0   0x11
#define CH7017_CHROMA_BOOST  0x14
#define CH7017_CLOCK_MODE  0x1c
#define CH7017_INPUT_CLOCK  0x1d
#define CH7017_GPIO_CONTROL  0x1e
#define CH7017_INPUT_DATA_FORMAT 0x1f
#define CH7017_CONNECTION_DETECT 0x20
#define CH7017_DAC_CONTROL  0x21
#define CH7017_BUFFERED_CLOCK_OUTPUT 0x22
#define CH7017_DEFEAT_VSYNC  0x47
#define CH7017_TEST_PATTERN  0x48

#define CH7017_POWER_MANAGEMENT  0x49
/** Enables the TV output path. */
#define CH7017_TV_EN   (1 << 0)
#define CH7017_DAC0_POWER_DOWN  (1 << 1)
#define CH7017_DAC1_POWER_DOWN  (1 << 2)
#define CH7017_DAC2_POWER_DOWN  (1 << 3)
#define CH7017_DAC3_POWER_DOWN  (1 << 4)
/** Powers down the TV out block, and DAC0-3 */
#define CH7017_TV_POWER_DOWN_EN  (1 << 5)

#define CH7017_VERSION_ID  0x4a

#define CH7017_DEVICE_ID  0x4b
#define CH7017_DEVICE_ID_VALUE  0x1b
#define CH7018_DEVICE_ID_VALUE  0x1a
#define CH7019_DEVICE_ID_VALUE  0x19

#define CH7017_XCLK_D2_ADJUST  0x53
#define CH7017_UP_SCALER_COEFF_0 0x55
#define CH7017_UP_SCALER_COEFF_1 0x56
#define CH7017_UP_SCALER_COEFF_2 0x57
#define CH7017_UP_SCALER_COEFF_3 0x58
#define CH7017_UP_SCALER_COEFF_4 0x59
#define CH7017_UP_SCALER_VERTICAL_INC_0 0x5a
#define CH7017_UP_SCALER_VERTICAL_INC_1 0x5b
#define CH7017_GPIO_INVERT  0x5c
#define CH7017_UP_SCALER_HORIZONTAL_INC_0 0x5d
#define CH7017_UP_SCALER_HORIZONTAL_INC_1 0x5e

#define CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT 0x5f
/**< Low bits of horizontal active pixel input */

#define CH7017_ACTIVE_INPUT_LINE_OUTPUT 0x60
/** High bits of horizontal active pixel input */
#define CH7017_LVDS_HAP_INPUT_MASK (0x7 << 0)
/** High bits of vertical active line output */
#define CH7017_LVDS_VAL_HIGH_MASK (0x7 << 3)

#define CH7017_VERTICAL_ACTIVE_LINE_OUTPUT 0x61
/**< Low bits of vertical active line output */

#define CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT 0x62
/**< Low bits of horizontal active pixel output */

#define CH7017_LVDS_POWER_DOWN  0x63
/** High bits of horizontal active pixel output */
#define CH7017_LVDS_HAP_HIGH_MASK (0x7 << 0)
/** Enables the LVDS power down state transition */
#define CH7017_LVDS_POWER_DOWN_EN (1 << 6)
/** Enables the LVDS upscaler */
#define CH7017_LVDS_UPSCALER_EN  (1 << 7)
#define CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED 0x08

#define CH7017_LVDS_ENCODING  0x64
#define CH7017_LVDS_DITHER_2D  (1 << 2)
#define CH7017_LVDS_DITHER_DIS  (1 << 3)
#define CH7017_LVDS_DUAL_CHANNEL_EN (1 << 4)
#define CH7017_LVDS_24_BIT  (1 << 5)

#define CH7017_LVDS_ENCODING_2  0x65

#define CH7017_LVDS_PLL_CONTROL  0x66
/** Enables the LVDS panel output path */
#define CH7017_LVDS_PANEN  (1 << 0)
/** Enables the LVDS panel backlight */
#define CH7017_LVDS_BKLEN  (1 << 3)

#define CH7017_POWER_SEQUENCING_T1 0x67
#define CH7017_POWER_SEQUENCING_T2 0x68
#define CH7017_POWER_SEQUENCING_T3 0x69
#define CH7017_POWER_SEQUENCING_T4 0x6a
#define CH7017_POWER_SEQUENCING_T5 0x6b
#define CH7017_GPIO_DRIVER_TYPE  0x6c
#define CH7017_GPIO_DATA  0x6d
#define CH7017_GPIO_DIRECTION_CONTROL 0x6e

#define CH7017_LVDS_PLL_FEEDBACK_DIV 0x71
define CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT 4
define CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT 0
define CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED 0x80

#define CH7017_LVDS_PLL_VCO_CONTROL 0x72
define CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED 0x80
define CH7017_LVDS_PLL_VCO_SHIFT 4
define CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT 0

#define CH7017_OUTPUTS_ENABLE  0x73
define CH7017_CHARGE_PUMP_LOW  0x0
define CH7017_CHARGE_PUMP_HIGH 0x3
define CH7017_LVDS_CHANNEL_A  (1 << 3)
define CH7017_LVDS_CHANNEL_B  (1 << 4)
define CH7017_TV_DAC_A  (1 << 5)
define CH7017_TV_DAC_B  (1 << 6)
define CH7017_DDC_SELECT_DC2  (1 << 7)

#define CH7017_LVDS_OUTPUT_AMPLITUDE 0x74
#define CH7017_LVDS_PLL_EMI_REDUCTION 0x75
#define CH7017_LVDS_POWER_DOWN_FLICKER 0x76

#define CH7017_LVDS_CONTROL_2  0x78
define CH7017_LOOP_FILTER_SHIFT 5
define CH7017_PHASE_DETECTOR_SHIFT 0

#define CH7017_BANG_LIMIT_CONTROL 0x7f

struct ch7017_priv {
 u8 dummy;
};

static void ch7017_dump_regs(struct intel_dvo_device *dvo);
static void ch7017_dpms(struct intel_dvo_device *dvo, bool enable);

static bool ch7017_read(struct intel_dvo_device *dvo, u8 addr, u8 *val)
{
 struct i2c_msg msgs[] = {
  {
   .addr = dvo->target_addr,
   .flags = 0,
   .len = 1,
   .buf = &addr,
  },
  {
   .addr = dvo->target_addr,
   .flags = I2C_M_RD,
   .len = 1,
   .buf = val,
  }
 };
 return i2c_transfer(dvo->i2c_bus, msgs, 2) == 2;
}

static bool ch7017_write(struct intel_dvo_device *dvo, u8 addr, u8 val)
{
 u8 buf[2] = { addr, val };
 struct i2c_msg msg = {
  .addr = dvo->target_addr,
  .flags = 0,
  .len = 2,
  .buf = buf,
 };
 return i2c_transfer(dvo->i2c_bus, &msg, 1) == 1;
}

/** Probes for a CH7017 on the given bus and target address. */
static bool ch7017_init(struct intel_dvo_device *dvo,
   struct i2c_adapter *adapter)
{
 struct ch7017_priv *priv;
 const char *str;
 u8 val;

 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 if (priv == NULL)
  return false;

 dvo->i2c_bus = adapter;
 dvo->dev_priv = priv;

 if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val))
  goto fail;

 switch (val) {
 case CH7017_DEVICE_ID_VALUE:
  str = "ch7017";
  break;
 case CH7018_DEVICE_ID_VALUE:
  str = "ch7018";
  break;
 case CH7019_DEVICE_ID_VALUE:
  str = "ch7019";
  break;
 default:
  DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
         "target %d.\n",
         val, adapter->name, dvo->target_addr);
  goto fail;
 }

 DRM_DEBUG_KMS("%s detected on %s, addr %d\n",
        str, adapter->name, dvo->target_addr);
 return true;

fail:
 kfree(priv);
 return false;
}

static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo)
{
 return connector_status_connected;
}

static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo,
           const struct drm_display_mode *mode)
{
 if (mode->clock > 160000)
  return MODE_CLOCK_HIGH;

 return MODE_OK;
}

static void ch7017_mode_set(struct intel_dvo_device *dvo,
       const struct drm_display_mode *mode,
       const struct drm_display_mode *adjusted_mode)
{
 u8 lvds_pll_feedback_div, lvds_pll_vco_control;
 u8 outputs_enable, lvds_control_2, lvds_power_down;
 u8 horizontal_active_pixel_input;
 u8 horizontal_active_pixel_output, vertical_active_line_output;
 u8 active_input_line_output;

 DRM_DEBUG_KMS("Registers before mode setting\n");
 ch7017_dump_regs(dvo);

 /* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/
 if (mode->clock < 100000) {
  outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_LOW;
  lvds_pll_feedback_div = CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED |
   (2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) |
   (13 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT);
  lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
   (2 << CH7017_LVDS_PLL_VCO_SHIFT) |
   (3 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
  lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) |
   (0 << CH7017_PHASE_DETECTOR_SHIFT);
 } else {
  outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_HIGH;
  lvds_pll_feedback_div =
   CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED |
   (2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) |
   (3 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT);
  lvds_control_2 = (3 << CH7017_LOOP_FILTER_SHIFT) |
   (0 << CH7017_PHASE_DETECTOR_SHIFT);
  if (1) { /* XXX: dual channel panel detection.  Assume yes for now. */
   outputs_enable |= CH7017_LVDS_CHANNEL_B;
   lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
    (2 << CH7017_LVDS_PLL_VCO_SHIFT) |
    (13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
  } else {
   lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
    (1 << CH7017_LVDS_PLL_VCO_SHIFT) |
    (13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
  }
 }

 horizontal_active_pixel_input = mode->hdisplay & 0x00ff;

 vertical_active_line_output = mode->vdisplay & 0x00ff;
 horizontal_active_pixel_output = mode->hdisplay & 0x00ff;

 active_input_line_output = ((mode->hdisplay & 0x0700) >> 8) |
       (((mode->vdisplay & 0x0700) >> 8) << 3);

 lvds_power_down = CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED |
     (mode->hdisplay & 0x0700) >> 8;

 ch7017_dpms(dvo, false);
 ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT,
   horizontal_active_pixel_input);
 ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT,
   horizontal_active_pixel_output);
 ch7017_write(dvo, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT,
   vertical_active_line_output);
 ch7017_write(dvo, CH7017_ACTIVE_INPUT_LINE_OUTPUT,
   active_input_line_output);
 ch7017_write(dvo, CH7017_LVDS_PLL_VCO_CONTROL, lvds_pll_vco_control);
 ch7017_write(dvo, CH7017_LVDS_PLL_FEEDBACK_DIV, lvds_pll_feedback_div);
 ch7017_write(dvo, CH7017_LVDS_CONTROL_2, lvds_control_2);
 ch7017_write(dvo, CH7017_OUTPUTS_ENABLE, outputs_enable);

 /* Turn the LVDS back on with new settings. */
 ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, lvds_power_down);

 DRM_DEBUG_KMS("Registers after mode setting\n");
 ch7017_dump_regs(dvo);
}

/* set the CH7017 power state */
static void ch7017_dpms(struct intel_dvo_device *dvo, bool enable)
{
 u8 val;

 ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &val);

 /* Turn off TV/VGA, and never turn it on since we don't support it. */
 ch7017_write(dvo, CH7017_POWER_MANAGEMENT,
   CH7017_DAC0_POWER_DOWN |
   CH7017_DAC1_POWER_DOWN |
   CH7017_DAC2_POWER_DOWN |
   CH7017_DAC3_POWER_DOWN |
   CH7017_TV_POWER_DOWN_EN);

 if (enable) {
  /* Turn on the LVDS */
  ch7017_write(dvo, CH7017_LVDS_POWER_DOWN,
        val & ~CH7017_LVDS_POWER_DOWN_EN);
 } else {
  /* Turn off the LVDS */
  ch7017_write(dvo, CH7017_LVDS_POWER_DOWN,
        val | CH7017_LVDS_POWER_DOWN_EN);
 }

 /* XXX: Should actually wait for update power status somehow */
 msleep(20);
}

static bool ch7017_get_hw_state(struct intel_dvo_device *dvo)
{
 u8 val;

 ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &val);

 if (val & CH7017_LVDS_POWER_DOWN_EN)
  return false;
 else
  return true;
}

static void ch7017_dump_regs(struct intel_dvo_device *dvo)
{
 u8 val;

#define DUMP(reg)     \
do {       \
 ch7017_read(dvo, reg, &val);   \
 DRM_DEBUG_KMS(#reg ": %02x\n", val);  \
while (0)

 DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT);
 DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT);
 DUMP(CH7017_VERTICAL_ACTIVE_LINE_OUTPUT);
 DUMP(CH7017_ACTIVE_INPUT_LINE_OUTPUT);
 DUMP(CH7017_LVDS_PLL_VCO_CONTROL);
 DUMP(CH7017_LVDS_PLL_FEEDBACK_DIV);
 DUMP(CH7017_LVDS_CONTROL_2);
 DUMP(CH7017_OUTPUTS_ENABLE);
 DUMP(CH7017_LVDS_POWER_DOWN);
}

static void ch7017_destroy(struct intel_dvo_device *dvo)
{
 struct ch7017_priv *priv = dvo->dev_priv;

 if (priv) {
  kfree(priv);
  dvo->dev_priv = NULL;
 }
}

const struct intel_dvo_dev_ops ch7017_ops = {
 .init = ch7017_init,
 .detect = ch7017_detect,
 .mode_valid = ch7017_mode_valid,
 .mode_set = ch7017_mode_set,
 .dpms = ch7017_dpms,
 .get_hw_state = ch7017_get_hw_state,
 .dump_regs = ch7017_dump_regs,
 .destroy = ch7017_destroy,
};

Messung V0.5
C=93 H=92 G=92

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.