linux/drivers/gpu/drm/i915/display/intel_sdvo.c

/*
 * Copyright 2006 Dave Airlie <[email protected]>
 * Copyright © 2006-2007 Intel Corporation
 *   Jesse Barnes <[email protected]>
 *
 * 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 <[email protected]>
 */

#include <linux/delay.h>
#include <linux/export.h>
#include <linux/i2c.h>
#include <linux/slab.h>

#include <drm/display/drm_hdmi_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_eld.h>

#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_connector.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_driver.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
#include "intel_fifo_underrun.h"
#include "intel_gmbus.h"
#include "intel_hdmi.h"
#include "intel_hotplug.h"
#include "intel_panel.h"
#include "intel_sdvo.h"
#include "intel_sdvo_regs.h"

#define SDVO_TMDS_MASK
#define SDVO_RGB_MASK
#define SDVO_LVDS_MASK
#define SDVO_TV_MASK

#define SDVO_OUTPUT_MASK

#define IS_TV(c)
#define IS_TMDS(c)
#define IS_LVDS(c)
#define IS_TV_OR_LVDS(c)
#define IS_DIGITAL(c)

#define HAS_DDC(c)

static const char * const tv_format_names[] =;

#define TV_FORMAT_NUM

struct intel_sdvo;

struct intel_sdvo_ddc {};

struct intel_sdvo {};

struct intel_sdvo_connector {};

struct intel_sdvo_connector_state {};

static struct intel_sdvo *to_sdvo(struct intel_encoder *encoder)
{}

static struct intel_sdvo *intel_attached_sdvo(struct intel_connector *connector)
{}

static struct intel_sdvo_connector *
to_intel_sdvo_connector(struct drm_connector *connector)
{}

#define to_intel_sdvo_connector_state(conn_state)

static bool
intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo);
static bool
intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
			      struct intel_sdvo_connector *intel_sdvo_connector,
			      int type);
static bool
intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo,
				   struct intel_sdvo_connector *intel_sdvo_connector);

/*
 * Writes the SDVOB or SDVOC with the given value, but always writes both
 * SDVOB and SDVOC to work around apparent hardware issues (according to
 * comments in the BIOS).
 */
static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
{}

static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch)
{}

#define SDVO_CMD_NAME_ENTRY

/** Mapping of command numbers to names, for debug output */
static const struct {} __packed sdvo_cmd_names[] =;

#undef SDVO_CMD_NAME_ENTRY

static const char *sdvo_cmd_name(u8 cmd)
{}

#define SDVO_NAME(svdo)

static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
				   const void *args, int args_len)
{}

static const char * const cmd_status_names[] =;

static const char *sdvo_cmd_status(u8 status)
{}

static bool __intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd,
				   const void *args, int args_len,
				   bool unlocked)
{}

static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd,
				 const void *args, int args_len)
{}

static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
				     void *response, int response_len)
{}

static int intel_sdvo_get_pixel_multiplier(const struct drm_display_mode *adjusted_mode)
{}

static bool __intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo,
						u8 ddc_bus)
{}

static bool intel_sdvo_set_value(struct intel_sdvo *intel_sdvo, u8 cmd, const void *data, int len)
{}

static bool
intel_sdvo_get_value(struct intel_sdvo *intel_sdvo, u8 cmd, void *value, int len)
{}

static bool intel_sdvo_set_target_input(struct intel_sdvo *intel_sdvo)
{}

/*
 * Return whether each input is trained.
 *
 * This function is making an assumption about the layout of the response,
 * which should be checked against the docs.
 */
static bool intel_sdvo_get_trained_inputs(struct intel_sdvo *intel_sdvo, bool *input_1, bool *input_2)
{}

static bool intel_sdvo_set_active_outputs(struct intel_sdvo *intel_sdvo,
					  u16 outputs)
{}

static bool intel_sdvo_get_active_outputs(struct intel_sdvo *intel_sdvo,
					  u16 *outputs)
{}

static bool intel_sdvo_set_encoder_power_state(struct intel_sdvo *intel_sdvo,
					       int mode)
{}

static bool intel_sdvo_get_input_pixel_clock_range(struct intel_sdvo *intel_sdvo,
						   int *clock_min,
						   int *clock_max)
{}

static bool intel_sdvo_set_target_output(struct intel_sdvo *intel_sdvo,
					 u16 outputs)
{}

static bool intel_sdvo_set_timing(struct intel_sdvo *intel_sdvo, u8 cmd,
				  struct intel_sdvo_dtd *dtd)
{}

static bool intel_sdvo_get_timing(struct intel_sdvo *intel_sdvo, u8 cmd,
				  struct intel_sdvo_dtd *dtd)
{}

static bool intel_sdvo_set_input_timing(struct intel_sdvo *intel_sdvo,
					struct intel_sdvo_dtd *dtd)
{}

static bool intel_sdvo_set_output_timing(struct intel_sdvo *intel_sdvo,
					 struct intel_sdvo_dtd *dtd)
{}

static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo,
					struct intel_sdvo_dtd *dtd)
{}

static bool
intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo,
					 struct intel_sdvo_connector *intel_sdvo_connector,
					 const struct drm_display_mode *mode)
{}

static bool intel_sdvo_get_preferred_input_timing(struct intel_sdvo *intel_sdvo,
						  struct intel_sdvo_dtd *dtd)
{}

static bool intel_sdvo_set_clock_rate_mult(struct intel_sdvo *intel_sdvo, u8 val)
{}

static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
					 const struct drm_display_mode *mode)
{}

static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode *pmode,
					 const struct intel_sdvo_dtd *dtd)
{}

static bool intel_sdvo_check_supp_encode(struct intel_sdvo *intel_sdvo)
{}

static bool intel_sdvo_set_encode(struct intel_sdvo *intel_sdvo,
				  u8 mode)
{}

static bool intel_sdvo_set_colorimetry(struct intel_sdvo *intel_sdvo,
				       u8 mode)
{}

static bool intel_sdvo_set_pixel_replication(struct intel_sdvo *intel_sdvo,
					     u8 pixel_repeat)
{}

static bool intel_sdvo_set_audio_state(struct intel_sdvo *intel_sdvo,
				       u8 audio_state)
{}

static bool intel_sdvo_get_hbuf_size(struct intel_sdvo *intel_sdvo,
				     u8 *hbuf_size)
{}

#if 0
static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
{
	int i, j;
	u8 set_buf_index[2];
	u8 av_split;
	u8 buf_size;
	u8 buf[48];
	u8 *pos;

	intel_sdvo_get_value(encoder, SDVO_CMD_GET_HBUF_AV_SPLIT, &av_split, 1);

	for (i = 0; i <= av_split; i++) {
		set_buf_index[0] = i; set_buf_index[1] = 0;
		intel_sdvo_write_cmd(encoder, SDVO_CMD_SET_HBUF_INDEX,
				     set_buf_index, 2);
		intel_sdvo_write_cmd(encoder, SDVO_CMD_GET_HBUF_INFO, NULL, 0);
		intel_sdvo_read_response(encoder, &buf_size, 1);

		pos = buf;
		for (j = 0; j <= buf_size; j += 8) {
			intel_sdvo_write_cmd(encoder, SDVO_CMD_GET_HBUF_DATA,
					     NULL, 0);
			intel_sdvo_read_response(encoder, pos, 8);
			pos += 8;
		}
	}
}
#endif

static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
				       unsigned int if_index, u8 tx_rate,
				       const u8 *data, unsigned int length)
{}

static ssize_t intel_sdvo_read_infoframe(struct intel_sdvo *intel_sdvo,
					 unsigned int if_index,
					 u8 *data, unsigned int length)
{}

static bool intel_sdvo_compute_avi_infoframe(struct intel_sdvo *intel_sdvo,
					     struct intel_crtc_state *crtc_state,
					     struct drm_connector_state *conn_state)
{}

static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
					 const struct intel_crtc_state *crtc_state)
{}

static void intel_sdvo_get_avi_infoframe(struct intel_sdvo *intel_sdvo,
					 struct intel_crtc_state *crtc_state)
{}

static void intel_sdvo_get_eld(struct intel_sdvo *intel_sdvo,
			       struct intel_crtc_state *crtc_state)
{}

static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo,
				     const struct drm_connector_state *conn_state)
{}

static bool
intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo,
					struct intel_sdvo_connector *intel_sdvo_connector,
					const struct drm_display_mode *mode)
{}

/*
 * Asks the sdvo controller for the preferred input mode given the output mode.
 * Unfortunately we have to set up the full output mode to do that.
 */
static bool
intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
				    struct intel_sdvo_connector *intel_sdvo_connector,
				    const struct drm_display_mode *mode,
				    struct drm_display_mode *adjusted_mode)
{}

static int i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config)
{}

static bool intel_has_hdmi_sink(struct intel_sdvo_connector *intel_sdvo_connector,
				const struct drm_connector_state *conn_state)
{}

static bool intel_sdvo_limited_color_range(struct intel_encoder *encoder,
					   const struct intel_crtc_state *crtc_state,
					   const struct drm_connector_state *conn_state)
{}

static bool intel_sdvo_has_audio(struct intel_encoder *encoder,
				 const struct intel_crtc_state *crtc_state,
				 const struct drm_connector_state *conn_state)
{}

static int intel_sdvo_compute_config(struct intel_encoder *encoder,
				     struct intel_crtc_state *pipe_config,
				     struct drm_connector_state *conn_state)
{}

#define UPDATE_PROPERTY

static void intel_sdvo_update_props(struct intel_sdvo *intel_sdvo,
				    const struct intel_sdvo_connector_state *sdvo_state)
{}

static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
				  struct intel_encoder *intel_encoder,
				  const struct intel_crtc_state *crtc_state,
				  const struct drm_connector_state *conn_state)
{}

static bool intel_sdvo_connector_get_hw_state(struct intel_connector *connector)
{}

bool intel_sdvo_port_enabled(struct drm_i915_private *dev_priv,
			     i915_reg_t sdvo_reg, enum pipe *pipe)
{}

static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
				    enum pipe *pipe)
{}

static void intel_sdvo_get_config(struct intel_encoder *encoder,
				  struct intel_crtc_state *pipe_config)
{}

static void intel_sdvo_disable_audio(struct intel_encoder *encoder,
				     const struct intel_crtc_state *old_crtc_state,
				     const struct drm_connector_state *old_conn_state)
{}

static void intel_sdvo_enable_audio(struct intel_encoder *encoder,
				    const struct intel_crtc_state *crtc_state,
				    const struct drm_connector_state *conn_state)
{}

static void intel_disable_sdvo(struct intel_atomic_state *state,
			       struct intel_encoder *encoder,
			       const struct intel_crtc_state *old_crtc_state,
			       const struct drm_connector_state *conn_state)
{}

static void pch_disable_sdvo(struct intel_atomic_state *state,
			     struct intel_encoder *encoder,
			     const struct intel_crtc_state *old_crtc_state,
			     const struct drm_connector_state *old_conn_state)
{}

static void pch_post_disable_sdvo(struct intel_atomic_state *state,
				  struct intel_encoder *encoder,
				  const struct intel_crtc_state *old_crtc_state,
				  const struct drm_connector_state *old_conn_state)
{}

static void intel_enable_sdvo(struct intel_atomic_state *state,
			      struct intel_encoder *encoder,
			      const struct intel_crtc_state *pipe_config,
			      const struct drm_connector_state *conn_state)
{}

static enum drm_mode_status
intel_sdvo_mode_valid(struct drm_connector *connector,
		      struct drm_display_mode *mode)
{}

static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct intel_sdvo_caps *caps)
{}

static u8 intel_sdvo_get_colorimetry_cap(struct intel_sdvo *intel_sdvo)
{}

static u16 intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo)
{}

static void intel_sdvo_enable_hotplug(struct intel_encoder *encoder)
{}

static enum intel_hotplug_state
intel_sdvo_hotplug(struct intel_encoder *encoder,
		   struct intel_connector *connector)
{}

static const struct drm_edid *
intel_sdvo_get_edid(struct drm_connector *connector)
{}

/* Mac mini hack -- use the same DDC as the analog connector */
static const struct drm_edid *
intel_sdvo_get_analog_edid(struct drm_connector *connector)
{}

static enum drm_connector_status
intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
{}

static bool
intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo,
				  const struct drm_edid *drm_edid)
{}

static enum drm_connector_status
intel_sdvo_detect(struct drm_connector *connector, bool force)
{}

static int intel_sdvo_get_ddc_modes(struct drm_connector *connector)
{}

/*
 * Set of SDVO TV modes.
 * Note!  This is in reply order (see loop in get_tv_modes).
 * XXX: all 60Hz refresh?
 */
static const struct drm_display_mode sdvo_tv_modes[] =;

static int intel_sdvo_get_tv_modes(struct drm_connector *connector)
{}

static int intel_sdvo_get_lvds_modes(struct drm_connector *connector)
{}

static int intel_sdvo_get_modes(struct drm_connector *connector)
{}

static int
intel_sdvo_connector_atomic_get_property(struct drm_connector *connector,
					 const struct drm_connector_state *state,
					 struct drm_property *property,
					 u64 *val)
{}

static int
intel_sdvo_connector_atomic_set_property(struct drm_connector *connector,
					 struct drm_connector_state *state,
					 struct drm_property *property,
					 u64 val)
{}

static struct drm_connector_state *
intel_sdvo_connector_duplicate_state(struct drm_connector *connector)
{}

static const struct drm_connector_funcs intel_sdvo_connector_funcs =;

static int intel_sdvo_atomic_check(struct drm_connector *conn,
				   struct drm_atomic_state *state)
{}

static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs =;

static void intel_sdvo_encoder_destroy(struct drm_encoder *_encoder)
{
	struct intel_encoder *encoder = to_intel_encoder(_encoder);
	struct intel_sdvo *sdvo = to_sdvo(encoder);
	int i;

	for (i = 0; i < ARRAY_SIZE(sdvo->ddc); i++) {
		if (sdvo->ddc[i].ddc_bus)
			i2c_del_adapter(&sdvo->ddc[i].ddc);
	}

	drm_encoder_cleanup(&encoder->base);
	kfree(sdvo);
};

static const struct drm_encoder_funcs intel_sdvo_enc_funcs =;

static int
intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo,
			 struct intel_sdvo_connector *connector)
{}

/*
 * Choose the appropriate DDC bus for control bus switch command for this
 * SDVO output based on the controlled output.
 *
 * DDC bus number assignment is in a priority order of RGB outputs, then TMDS
 * outputs, then LVDS outputs.
 */
static struct intel_sdvo_ddc *
intel_sdvo_select_ddc_bus(struct intel_sdvo *sdvo,
			  struct intel_sdvo_connector *connector)
{}

static void
intel_sdvo_select_i2c_bus(struct intel_sdvo *sdvo)
{}

/* undo any changes intel_sdvo_select_i2c_bus() did to sdvo->i2c */
static void
intel_sdvo_unselect_i2c_bus(struct intel_sdvo *sdvo)
{}

static bool
intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo)
{}

static u8
intel_sdvo_get_target_addr(struct intel_sdvo *sdvo)
{}

static int
intel_sdvo_init_ddc_proxy(struct intel_sdvo_ddc *ddc,
			  struct intel_sdvo *sdvo, int bit);

static int
intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
			  struct intel_sdvo *encoder)
{}

static void
intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo,
			       struct intel_sdvo_connector *connector)
{}

static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void)
{}

static bool
intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, u16 type)
{}

static bool
intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, u16 type)
{}

static bool
intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, u16 type)
{}

static bool
intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, u16 type)
{}

static u16 intel_sdvo_filter_output_flags(u16 flags)
{}

static bool intel_sdvo_output_init(struct intel_sdvo *sdvo, u16 type)
{}

static bool
intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo)
{}

static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo)
{}

static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
					  struct intel_sdvo_connector *intel_sdvo_connector,
					  int type)
{}

#define _ENHANCEMENT

#define ENHANCEMENT

static bool
intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo,
				      struct intel_sdvo_connector *intel_sdvo_connector,
				      struct intel_sdvo_enhancements_reply enhancements)
{}

static bool
intel_sdvo_create_enhance_property_lvds(struct intel_sdvo *intel_sdvo,
					struct intel_sdvo_connector *intel_sdvo_connector,
					struct intel_sdvo_enhancements_reply enhancements)
{}
#undef ENHANCEMENT
#undef _ENHANCEMENT

static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo,
					       struct intel_sdvo_connector *intel_sdvo_connector)
{}

static int intel_sdvo_ddc_proxy_xfer(struct i2c_adapter *adapter,
				     struct i2c_msg *msgs,
				     int num)
{}

static u32 intel_sdvo_ddc_proxy_func(struct i2c_adapter *adapter)
{}

static const struct i2c_algorithm intel_sdvo_ddc_proxy =;

static void proxy_lock_bus(struct i2c_adapter *adapter,
			   unsigned int flags)
{}

static int proxy_trylock_bus(struct i2c_adapter *adapter,
			     unsigned int flags)
{}

static void proxy_unlock_bus(struct i2c_adapter *adapter,
			     unsigned int flags)
{}

static const struct i2c_lock_operations proxy_lock_ops =;

static int
intel_sdvo_init_ddc_proxy(struct intel_sdvo_ddc *ddc,
			  struct intel_sdvo *sdvo, int ddc_bus)
{}

static bool is_sdvo_port_valid(struct drm_i915_private *dev_priv, enum port port)
{}

static bool assert_sdvo_port_valid(struct drm_i915_private *dev_priv,
				   enum port port)
{}

bool intel_sdvo_init(struct drm_i915_private *dev_priv,
		     i915_reg_t sdvo_reg, enum port port)
{}